TL;博士
这确实是Motor 1.2.0中的一个bug,由a.Jesse Jiryu Davis及时修复,并在1.2.1或更高版本的驱动程序中提供。
原始问题
我在Python 3上编写了一个程序,使用MongoDB集合的新更改流特性来监视对MongoDB集合的更改。以下是MCVE:
from asyncio import get_event_loop, CancelledError
from contextlib import suppress
from motor.motor_asyncio import AsyncIOMotorClient
async def watch(collection):
async with collection.watch([]) as stream:
async for change in stream:
print(change)
async def cleanup():
task.cancel()
with suppress(CancelledError):
await task
if __name__ == '__main__':
conn = AsyncIOMotorClient()
loop = get_event_loop()
task = loop.create_task(watch(conn.database.collection)) # Replace with a real collection.
try:
loop.run_forever()
except KeyboardInterrupt:
pass
finally:
loop.run_until_complete(cleanup())
loop.shutdown_asyncgens()
loop.close()
当我用CTRL+C终止程序时,它会引发三个不同的异常。
^Cexception calling callback for <Future at 0x102efea58 state=finished raised InvalidStateError>
Traceback (most recent call last):
File "/Users/viotti/motor/lib/python3.6/site-packages/motor/core.py", line 1259, in _next
change = self.delegate.next()
File "/Users/viotti/motor/lib/python3.6/site-packages/pymongo/change_stream.py", line 79, in next
change = self._cursor.next()
File "/Users/viotti/motor/lib/python3.6/site-packages/pymongo/command_cursor.py", line 292, in next
raise StopIteration
StopIteration
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/concurrent/futures/thread.py", line 56, in run
result = self.fn(*self.args, **self.kwargs)
File "/Users/viotti/motor/lib/python3.6/site-packages/motor/core.py", line 1264, in _next
future.set_exception(StopAsyncIteration())
asyncio.base_futures.InvalidStateError: invalid state
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/concurrent/futures/_base.py", line 324, in _invoke_callbacks
callback(self)
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/asyncio/futures.py", line 414, in _call_set_state
dest_loop.call_soon_threadsafe(_set_state, destination, source)
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/asyncio/base_events.py", line 620, in call_soon_threadsafe
self._check_closed()
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/asyncio/base_events.py", line 357, in _check_closed
raise RuntimeError('Event loop is closed')
RuntimeError: Event loop is closed
有没有办法让程序安静地关闭?
我正在macOS Sierra上使用Python 3.6.4、Motor 1.2和pymongo 3.6.0进行测试。