Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/353.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/7/rust/4.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 为什么asyncio.Queue无法按预期工作?_Python_Zeromq_Pyzmq_Python Asyncio - Fatal编程技术网

Python 为什么asyncio.Queue无法按预期工作?

Python 为什么asyncio.Queue无法按预期工作?,python,zeromq,pyzmq,python-asyncio,Python,Zeromq,Pyzmq,Python Asyncio,我正在写一个简单的制作人/消费者程序 import zmq @asyncio.coroutine def receive_data(future,s): print("begin to recv sth from.....socket" my_data = s.recv() future.set_result(my_data) @asyncio.coroutine def producer(loop,q,s): while Tr

我正在写一个简单的制作人/消费者程序

import zmq

@asyncio.coroutine
def receive_data(future,s):
        print("begin to recv sth from.....socket"
        my_data = s.recv()
        future.set_result(my_data)

@asyncio.coroutine
def producer(loop,q,s):
        while True:
                future = asyncio.Future()
                yield from receive_data(future,s)
                data = str(future.result())
                yield from q.put(data)
@asyncio.coroutine
def consumer(loop,q):
       while True:
          a = yield from q.get()
          print("i am get..."+str(a)+"..."+str(type(a)))  
loop = asyncio.get_event_loop()

c = zmq.Context()
s = c.socket(zmq.REP)
s.bind('tcp://127.0.0.1:5515')

q = asyncio.Queue()
tasks=[asyncio.Task(producer(loop,q,s)),asyncio.Task(comsumer(loop,q))]
loop.run_until_complete(asyncio.gather(*tasks))
loop.close()
s.close()
消费者似乎没有机会执行

套接字每500ms接收一次数据,因此当接收数据函数中的
产生时,暂停生产者协同程序,消费者协同程序将打印信息

有什么可以解释这一点呢?

s.recv()
正在阻止调用,所以
接收\u数据
直到新的ZMQ消息到达

这会阻塞事件循环,使用者没有机会自行执行

如果没有可用数据,您可以将
zmq.NOBLOCK
标志传递给
.recv
,并调用
asyncio.sleep(0)
,使eventloop有机会迭代其他就绪任务


或者只使用library:)

如果混合使用同步和异步调用,结果将是同步的。
如果要继续使用asyncio,应定义异步上下文
c=zmq.asyncio.context()
并使用路由器套接字
s=c.socket(zmq.ROUTER)
。然后,按照asyncio语法,您应该从
recv\u multipart()
中获得收益,这样您的
my\u data=s.recv()
就变成了
my\u data=yield from s s.recv\u multipart()

以下是需要执行的操作指南:

  • 您应该使用
    zmq.asyncio中的
    Context
    ZMQEventLoop
  • 您应该通过调用
    set\u event\u loop()
  • 仅出于测试目的,我已切换到路由器\u原始套接字
工作示例:

import asyncio
import zmq
from zmq.asyncio import Context, ZMQEventLoop

async def receive_data(s):
        data = await s.recv()
        print('receive_data', data)
        return data

async def producer(q, s):
        while True:
                data = await receive_data(s)
                await q.put(data)

async def consumer(q):
       while True:
          a = await q.get()
          print('i got... {} ... {}'.format(a, type(a)))  

loop = ZMQEventLoop()
asyncio.set_event_loop(loop)

c = Context()
s = c.socket(zmq.ROUTER)
s.setsockopt(zmq.ROUTER_RAW, 1)
s.bind('tcp://127.0.0.1:5515')

q = asyncio.Queue()
tasks=[producer(q, s), consumer(q)]
loop.run_until_complete(asyncio.gather(*tasks))
loop.close()
s.close()
您可以使用telnet使用ROUTER_RAW进行测试:

$ telnet localhost 5515
Trying ::1...
telnet: connect to address ::1: Connection refused
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
test
abcd1234
^]
telnet> Connection closed.
$ 
应用程序对此的响应是:

receive_data b'\x00\xa3\x8e\x1f)'
receive_data b''
i got... b'\x00\xa3\x8e\x1f)' ... <class 'bytes'>
i got... b'' ... <class 'bytes'>
receive_data b'\x00\xa3\x8e\x1f)'
receive_data b'test\r\n'
i got... b'\x00\xa3\x8e\x1f)' ... <class 'bytes'>
i got... b'test\r\n' ... <class 'bytes'>
receive_data b'\x00\xa3\x8e\x1f)'
receive_data b'abcd1234\r\n'
i got... b'\x00\xa3\x8e\x1f)' ... <class 'bytes'>
i got... b'abcd1234\r\n' ... <class 'bytes'>
receive_data b'\x00\xa3\x8e\x1f)'
receive_data b''
i got... b'\x00\xa3\x8e\x1f)' ... <class 'bytes'>
i got... b'' ... <class 'bytes'>
receive_data b'\x00\xa3\x8e\x1f)'
接收数据b''
我得到了。。。b'\x00\xa3\x8e\x1f)'。。。
我得到了。。。b''。。。
接收_数据b'\x00\xa3\x8e\x1f)'
接收\u数据b'测试\r\n'
我得到了。。。b'\x00\xa3\x8e\x1f)'。。。
我得到了。。。b'测试\r\n'。。。
接收_数据b'\x00\xa3\x8e\x1f)'
接收数据b'abcd1234\r\n'
我得到了。。。b'\x00\xa3\x8e\x1f)'。。。
我得到了。。。b'abcd1234\r\n'。。。
接收_数据b'\x00\xa3\x8e\x1f)'
接收数据b''
我得到了。。。b'\x00\xa3\x8e\x1f)'。。。
我得到了。。。b''。。。

或者您可以使用路由器/经销商,因为这是一种异步请求-应答模式。看见