#python #python-3.x #multithreading #python-asyncio
Вопрос:
В настоящее время у меня есть этот фрагмент кода, который отлично работает с помощью AsyncIO.
async def main():
while(1):
loop.create_task(startAsyncJob())
await asyncio.sleep(1)
async def startAsyncJob():
#myCodeHere
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
Я попытался добавить многопоточный слой, чтобы я мог одновременно запускать несколько фрагментов того, что находится внутри моего «основного». Поэтому я извлек его код, поместил его в собственную функцию AsyncJobThread
, которую запускаю через свою новую основную функцию с помощью потоков:
def main():
try:
_thread.start_new_thread( AsyncJobThread, (1))
_thread.start_new_thread( AsyncJobThread, (15))
except:
print ("Error: unable to start thread")
async def AsyncJobThread(frequence):
while(1):
loop.create_task(startAsyncJob())
await asyncio.sleep(frequence)
async def startAsyncJob():
#myCodeHere
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
Однако текущая реализация выдает мне следующую ошибку:
sys:1: RuntimeWarning: coroutine 'AsyncJobThread' was never awaited
RuntimeWarning: Enable tracemalloc to get the object allocation traceback
Комментарии:
1. Вы не можете так смешивать потоки и асинхронность. Вам нужно будет запустить новый цикл событий внутри каждого потока. Почему бы вместо этого не использовать что-то вроде
asyncio.gather
запуска нескольких задач одновременно?2. Никогда не использовал ничего подобного, на самом деле я только вчера начал использовать asyncio. Не могли бы вы подробно рассказать, как бы вы это
asyncio.gather
сделали, в ответе, пожалуйста?3. @dirn Спасибо, я только что попробовал использовать новый цикл событий для каждого потока, и это сработало.
4. Кстати, нет причин использовать
_thread
вместоthreading.Thread
этого . (или, возможно, есть, но вам действительно нужно знать, что вы делаете). Как правило, если что-то начинается с_
Python, вы не должны использовать это напрямую (это эквивалент «частных» переменных в других языках).
Ответ №1:
Как и было запрошено, вот ваш код, измененный для использования asyncio.gather
.
async def main():
await asyncio.gather(
AsyncJobThread(1),
AsyncJobThread(15),
)
async def AsyncJobThread(frequence):
loop = asyncio.get_event_loop()
while True:
loop.create_task(startAsyncJob())
await asyncio.sleep(frequence)
async def startAsyncJob():
#myCodeHere
asyncio.run(main())
Вы также можете получить ссылку на цикл и передать ее, AsyncJobThread
если хотите.