#python #multithreading #python-asyncio
Вопрос:
Нет никаких проблем с использованием asyncio следующим образом.
import asyncio
async def main():
await asyncio.sleep(1)
aaa = 1
print (aaa)
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
loop.close()
Однако я должен использовать asyncio в потоке, как показано в простом коде ниже, что приводит к следующей ошибке
import asyncio
import threading
async def main():
await asyncio.sleep(1)
aaa = 1
print (aaa)
def test():
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
loop.close()
t=threading.Thread(target=test)
t.start()
Сообщение об ошибке (Ошибка выполнения: В потоке «Поток-1» отсутствует текущий цикл событий.)
Exception in thread Thread-1:
Traceback (most recent call last):
File "D:Anaconda3Libthreading.py", line 932, in _bootstrap_inner
self.run()
File "D:Anaconda3Libthreading.py", line 870, in run
self._target(*self._args, **self._kwargs)
File "D:/Test/Test4/main.py", line 57, in test
loop = asyncio.get_event_loop()
File "D:Anaconda3Libasyncioevents.py", line 639, in get_event_loop
raise RuntimeError('There is no current event loop in thread %r.'
RuntimeError: There is no current event loop in thread 'Thread-1'.
Как я могу использовать asyncio в потоке?
Это очень важно для меня. Я два дня боролся с этой проблемой.
Я был бы признателен вам за помощь.
Ответ №1:
При использовании потока, отличного от основного потока, вам необходимо установить цикл событий
def test():
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
loop.run_until_complete(main())
loop.close()
Ответ №2:
Если вам не нужно работать с уже существующим циклом событий (не в данном случае) или поддерживать Python 3.6, используйте asyncio.run
вместо ручной обработки цикла:
def test():
asyncio.run(main())
Это всегда гарантирует наличие допустимого цикла событий, а также обеспечивает надлежащую очистку.
Эта функция всегда создает новый цикл событий и закрывает его в конце. Он должен использоваться в качестве основной точки входа для программ asyncio и в идеале должен вызываться только один раз.
Обратите внимание, что при объединении asyncio
с потоками цикл событий обычно должен выполняться в основном цикле (см., например, bpo#34697). Вместо того , чтобы создавать поток для asyncio
, предпочитайте создавать поток для синхронных частей вашей программы.
# launch synchronous work in child threads
t=threading.Thread(target=my_sync_tasks)
t.start()
# launch asynchronous work in main thread
asyncio.run(main())
t.join()