Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/325.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/logging/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python gevent至Tornado ioloop-带协同程序/生成器的结构代码_Python_Asynchronous_Tornado_Gevent - Fatal编程技术网

Python gevent至Tornado ioloop-带协同程序/生成器的结构代码

Python gevent至Tornado ioloop-带协同程序/生成器的结构代码,python,asynchronous,tornado,gevent,Python,Asynchronous,Tornado,Gevent,我正在尝试转换一些相当简单的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() 我可

我正在尝试转换一些相当简单的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
中心可以安排代码的其他部分。当收到值时,函数返回值

我读了,我想用Tornado iLoop运行它(也是因为我想在IPython笔记本中运行它)。以下是一个选项,其中
recv\u 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生成器构造代码的正确方法是什么?我是否必须使每个函数都成为一个生成器才能使其工作?如果我需要从
\uuuu init\uuuu()
调用其中一个函数,该怎么办?这也应该成为一个发电机吗

如果我需要从
\uuuu init\uuuu()
调用其中一个函数,该怎么办?应该 那也会变成发电机吗

这是使用
yield
/
yield from
(在Python 3.3+上)的显式异步编程目前尚未解决的问题之一。魔法方法不支持它们。您可以阅读Python核心开发人员关于异步编程的一些有趣想法,这些想法涉及到这个问题

使用Python生成器构造代码的正确方法是什么? 我是否必须使每个函数都成为一个生成器才能使其工作? 不是每个函数,而是要调用协同路由的每个函数,并等待该协同路由完成后再继续。当您切换到一个显式异步编程模型时,您通常希望完全使用它——您的整个程序都在tornado ioloop中运行。因此,在这个玩具示例中,您只需执行以下操作:

看起来您可以通过以下方式访问ioloop IPython正在使用的iLoop:

[4]中的
:来自IPython.kernel.ioloop导入管理器
[5]中:manager.ioloop.ioloop.instance()
出[5]:
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
In [4]: from IPython.kernel.ioloop import manager

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