0

我想在协程之间同步数据,最终得到一个方法,只要其中有“yield”就不会被调用。

更准确地说,当我按照文档(受此启发)使用方法 datagram_received 实现 DatagramProtocol 类时,一切正常,我收到了数据。一旦我在方法 datagram_received 中添加“yield”,该方法就不再被调用。这是一个例子:

loop = asyncio.get_event_loop()
lock = asyncio.Lock(loop=loop)

class MyProtocol(asyncio.DatagramProtocol):
    def datagram_received(self, data, addr):
        global my_data, lock
        print("here")
        # uncomment the following lines and datagram_received is 
        # not called at all (never see the "here" on the console)
        #yield from lock
        #try:
        #    my_data = float(data.decode())
        #finally:
        #    lock.release()

loop.run_until_complete(loop.create_datagram_endpoint(MyProtocol, sock=create_socket(10000)))

loop.run_forever()

根据方法的内容,如何突然不调用方法?

我错过了什么?应该如何进行同步?

4

1 回答 1

1

我错过了什么?

启发您的文档还指出:

可以使用 ensure_future() 在协议方法中调度协程,但不能保证执行顺序。协议不知道协议方法中创建的协程,因此不会等待它们。

要获得可靠的执行顺序,请在带有 yield from 的协程中使用流对象。例如,可以使用 StreamWriter.drain() 协程等到写入缓冲区被刷新。

你不能yield from/ awaitinside datagram_received,你可以:

class MyProtocol(asyncio.DatagramProtocol):
    def datagram_received(self, data, addr):
        global my_data, lock
        print("here")
        loop.ensure_future(some_function())
        
    @asyncio.coroutine
    def some_function(self):
        yield from lock
        try:
            my_data = float(data.decode())
        finally:
            lock.release()

根据方法的内容,如何突然不调用方法?

在函数中使用yieldor yield from,使其成为生成器。所以datagram_received返回生成器对象。要实际执行代码(直到产生),您应该使用next,asyncio 使用(基于生成器的)协程(但又不是datagram_received一个)

>>> def test():
...     print('test')
...     yield from 'A'
... 
>>> test()
<generator object test at 0x7f4165d42fc0>
>>> next(test())
test
'A'

有关生成器的更多信息:https ://jeffknupp.com/blog/2013/04/07/improve-your-python-yield-and-generators-explained/

于 2017-11-26T03:16:21.140 回答