Python 如何在异步IO中使用线程?
我想新建一个线程,在异步io任务中使用使用者/生产者模式执行io任务:Python 如何在异步IO中使用线程?,python,multithreading,python-asyncio,Python,Multithreading,Python Asyncio,我想新建一个线程,在异步io任务中使用使用者/生产者模式执行io任务: import asyncio import threading import time import queue q = queue.Queue() def consumer(): while True: v = q.get() time.sleep(v) print(f"log {v}") async def work(v):
import asyncio
import threading
import time
import queue
q = queue.Queue()
def consumer():
while True:
v = q.get()
time.sleep(v)
print(f"log {v}")
async def work(v):
await asyncio.sleep(0.1)
print(f"work {v}")
async def main():
t = threading.Thread(target=consumer, daemon=True)
t.start()
for i in range(1, 5):
print(f"start {i}")
q.put(i)
loop.create_task(work(i))
print(f"done {i}")
t.join()
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
loop.run_forever()
但是,由于使用者线程的原因,无法执行asyncio任务。您可以使用asyncio中内置的线程池(或创建自己的线程池,如果您愿意),并调用
run in_executor
向其提交任务,而不是显式管理工作线程和队列。例如:
import asyncio, time
def blocking_work(v):
# this function is not async, it will be run in a separate thread
time.sleep(v)
print(f"log {v}")
async def work(v):
# native asyncio work
await asyncio.sleep(0.1)
# followed by blocking IO wrapped in thread
loop = asyncio.get_event_loop()
await loop.run_in_executor(None, blocking_work, v)
print(f"work {v}")
async def main():
await asyncio.gather(*[work(i) for i in range(1, 5)])
asyncio.run(main())
您可以使用内置在asyncio中的线程池(或者根据需要创建自己的线程池)并调用
run\u in\u executor
向其提交任务,而不是显式管理工作线程和队列。例如:
import asyncio, time
def blocking_work(v):
# this function is not async, it will be run in a separate thread
time.sleep(v)
print(f"log {v}")
async def work(v):
# native asyncio work
await asyncio.sleep(0.1)
# followed by blocking IO wrapped in thread
loop = asyncio.get_event_loop()
await loop.run_in_executor(None, blocking_work, v)
print(f"work {v}")
async def main():
await asyncio.gather(*[work(i) for i in range(1, 5)])
asyncio.run(main())
异步IO中的IO不使用线程。为什么asyncio文档中的线程不适合您?@Romankonova事实上,如果您需要在磁盘中读取/写入文件,或者如果您有一些阻塞函数,Python中的线程仍然值得与asyncio一起使用。@Romankonova就像ArtiomKozyrev说的,我想gzip一个大文件,但我不想阻止主事件循环。在这种情况下,您没有执行IO。您正在调用一个阻塞函数,该函数在内部执行许多操作(包括一些IO)。这个问题具有误导性。问题
如何使用线程在异步IO中执行IO?
的正确答案是不要执行此操作。问题如何在asyncio中使用线程来阻止操作是合法的。gzip这是一项CPU受限的任务,因此Python中的线程不会因为GIL而对您有所帮助。您需要asyncio.loop.run_in_executor
,并结合ProcessPoolExecutor
在异步IO中不使用线程。为什么asyncio文档中的线程不适合您?@Romankonova事实上,如果您需要在磁盘中读取/写入文件,或者如果您有一些阻塞函数,Python中的线程仍然值得与asyncio一起使用。@Romankonova就像ArtiomKozyrev说的,我想gzip一个大文件,但我不想阻止主事件循环。在这种情况下,您没有执行IO。您正在调用一个阻塞函数,该函数在内部执行许多操作(包括一些IO)。这个问题具有误导性。问题如何使用线程在异步IO中执行IO?
的正确答案是不要执行此操作。问题如何在asyncio中使用线程来阻止操作是合法的。gzip这是一项CPU受限的任务,因此Python中的线程不会因为GIL而对您有所帮助。您需要asyncio.loop.run_in_executor
,与ProcessPoolExecutor