Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/290.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何在异步IO中使用线程?_Python_Multithreading_Python Asyncio - Fatal编程技术网

Python 如何在异步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):

我想新建一个线程,在异步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):
    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