asyncio.run завершается ошибкой, когда loop.run_until_complete работает
Этот код не работает:
import asyncio
from motor import motor_asyncio
_client = motor_asyncio.AsyncIOMotorClient()
_db = _client.db
users = _db.users
async def main():
await users.create_index(
'login',
unique=True
)
if __name__ == '__main__':
#loop = asyncio.get_event_loop()
#loop.run_until_complete(main())
asyncio.run(main())
С этой ошибкой:
Traceback (most recent call last):
File "/home/sanyash/myrepos/TKP/db.py", line 21, in <module>
asyncio.run(main())
File "/usr/local/lib/python3.7/asyncio/runners.py", line 43, in run
return loop.run_until_complete(main)
File "/usr/local/lib/python3.7/asyncio/base_events.py", line 584, in run_until_complete
return future.result()
File "/home/sanyash/myrepos/TKP/db.py", line 14, in main
unique=True
RuntimeError: Task <Task pending coro=<main() running at /home/sanyash/myrepos/TKP/db.py:14> cb=[_run_until_complete_cb() at /usr/local/lib/python3.7/asyncio/base_events.py:158]> got Future <Future pending cb=[run_on_executor.<locals>._call_check_cancel() at /usr/local/lib/python3.7/motor/frameworks/asyncio/__init__.py:80]> attached to a different loop
Когда я раскомментирую две строки loop
и комментарий asyncio.run
это работает хорошо. В чем дело? я думал asyncio.run
является ярлыком для этих двух строк.
Проблема в чем-то motor_asyncio
реализация, потому что, когда я изменился main
к простому return 42
, asyncio.run
тоже хорошо работает
1 ответ
В чем дело? я думал
asyncio.run
является ярлыком для этих двух строк.
Нет, это намного больше. В частности, он создает и устанавливает новый цикл обработки событий. И вот почему вы получаете ошибку: AsyncIOMotorClient()
создает некоторый асинхронный материал для цикла событий по умолчанию, но другой цикл, созданный asyncio.run
пытается использовать это.
Если вы хотите сохранить asyncio.run
Вы должны переместить инициалы внутри main()
:
# ...
_client = None
_db = None
users = None
async def main():
global _client, _db, users
_client = motor_asyncio.AsyncIOMotorClient()
_db = _client.db
users = _db.users
# ...
В общем, хорошая идея начинать все, когда цикл событий уже установлен и работает, а не делать что-то на уровне модуля.