我正在编写简单的生产者/消费者计划。
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()
消费者似乎没有机会执行。
套接字每500毫秒接收一次数据,所以当receive_data函数中的yield from
暂停生产者协程时,消费者协程将打印信息。
有什么可以解释这个?
答案 0 :(得分:3)
s.recv()
阻止了呼叫,因此receive_data
挂起,直到新的ZMQ消息到达。
阻止事件循环,消费者没有机会自行执行。
您可以将zmq.NOBLOCK
标记传递给.recv
并在没有可用数据的情况下调用asyncio.sleep(0)
,以便eventloop有机会迭代其他就绪任务。
或者只使用aiozmq库:)
答案 1 :(得分:1)
您正在混合同步和异步调用,结果将是同步的。
如果要继续使用asyncio,则应定义异步上下文c = zmq.asyncio.context()
并使用ROUTER套接字s = c.socket(zmq.ROUTER)
。然后,遵循asyncio语法,您应该从recv_multipart()
得出,以便my_data = s.recv()
成为my_data = yield from s.recv_multipart()
。
答案 2 :(得分:0)
以下是需要发生的事情的指南:
Context
ZMQEventLoop
和zmq.asyncio
asyncio
set_event_loop()
使用zmq循环
工作示例:
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'>