加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Python > 正文

python – gevent to Tornado ioloop – 结构代码与协同程序/生

发布时间:2020-12-20 13:44:22 所属栏目:Python 来源:网络整理
导读:我正在尝试转换一些相当简单的gevent代码来使用Tornado的异步工具.下面的示例代码使用ZMQ库来执行非常简单的请求 – 响应. import zmq.green as zmqdef fun(): i = zmq.Context.instance() sock = i.socket(zmq.REQ) sock.connect('tcp://localhost:9005') s
我正在尝试转换一些相当简单的gevent代码来使用Tornado的异步工具.下面的示例代码使用ZMQ库来执行非常简单的请求 – 响应.

import zmq.green as zmq

def fun():
    i = zmq.Context.instance()
    sock = i.socket(zmq.REQ)
    sock.connect('tcp://localhost:9005')
    sock.send('Ping')
    return sock.recv()

我可以在我的代码中的任何地方运行它作为fun(). .recv()调用在等待回复时阻塞,gevent中心可以调度代码的其他部分.收到值时,函数返回值.

我读了problems that can arise with these implicit returns,我想使用Tornado IOLoop来运行它(也因为我想在IPython Notebook中运行它).以下是一个选项,其中recv_future()返回包含结果的Future:

@gen.coroutine
def fun():
    i = zmq.Context.instance()
    sock = i.socket(zmq.REQ)
    sock.connect('tcp://localhost:9005')
    sock.send('Ping')
    msg = yield recv_future(sock)
    print "Received {}".format(msg[0])
    raise gen.Return(msg)

def recv_future(socket):
    zmqstream = ZMQStream(socket)  # Required for ZMQ
    future = Future()
    def _finish(reply):
        future.set_result(reply)
    zmqstream.on_recv(_finish)
    return future

问题是现在fun()不是一个函数,而是一个生成器.因此,如果我需要从另一个函数调用它,我需要使用yield fun().但随后调用函数也变成了生成器!

构建使用Python生成器的代码的正确方法是什么?我是否必须使每个功能都成为发电机才能使其工作?如果我需要从__init __()调用其中一个函数怎么办?那还应该成为发电机吗?

解决方法

What if I need to call one of these functions from __init__()? Should
that also become a generator?

这是目前未解决的问题之一,具有产率/收益率的显式异步编程(在Python 3.3上).魔术方法不支持它们.您可以阅读Python核心开发人员关于异步编程的一些有趣想法,这些想法涉及到这个问题here.

What is the right way to structure code that uses Python generators?
Do I have to make every function a generator to make it work?
Not every function,but every function that you want to call a coroutine,and wait for that coroutine to finish before continuing. When you switch to an explicit asynchronous programming model,you generally want to go all-in with it – your entire program runs inside the tornado ioloop. So,with this toy example,you would just do:

from tornado.ioloop import IOLoop
from tornado.gen import coroutine
from tornado.concurrent import Future

@gen.coroutine
def fun():
    i = zmq.Context.instance()
    sock = i.socket(zmq.REQ)
    sock.connect('tcp://localhost:9005')
    sock.send('Ping')
    msg = yield recv_future(sock)
    print "Received {}".format(msg[0])
    raise gen.Return(msg)

def recv_future(socket):
    zmqstream = ZMQStream(socket)  # Required for ZMQ
    future = Future()
    def _finish(reply):
        future.set_result(reply)
    zmqstream.on_recv(_finish)
    return future

if __name__ == "__main__":
    ioloop = IOLoop.instance()
    ioloop.add_callback(fun)
    ioloop.start() # This will run fun,and then block forever.
    #ioloop.run_sync(fun) # This will start the ioloop,run fun,then stop the ioloop

看起来您可以通过IPython.kernel API访问ioloop IPython正在使用:

In [4]: from IPython.kernel.ioloop import manager

In [5]: manager.ioloop.IOLoop.instance()
Out[5]: <zmq.eventloop.ioloop.ZMQIOLoop at 0x4249ac8>

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读