【问题标题】:using asyncio and threads使用异步和线程
【发布时间】:2017-07-31 10:59:02
【问题描述】:

在同一个 python 项目中同时使用 asyncio 和 threading 是否有意义,以便代码在不同的线程中运行,其中一些 asyncio 用于获取异步活动的顺序查找代码?

或者尝试这样做意味着我缺少关于线程或异步使用的一些基本概念?

【问题讨论】:

标签: python-3.x python-multithreading python-asyncio


【解决方案1】:

当然,这可能是有道理的。

异步代码原则上在同一个线程中运行一堆例程。

这意味着当一个例程必须等待输入或输出 (I/O) 时,它将暂时停止该例程并简单地开始处理另一个例程,直到它在那里遇到等待,等等。

多线程(或“并行”代码)原则上同时在您机器的不同内核上运行。 (请注意,在 Python 中,并行处理是通过使用下面@Yassine Faris 指出的多个进程来实现的。

在同一个程序中同时使用两者可能非常有意义。使用 asyncio 以便在等待 I/O 时继续处理。使用多线程(Python 中的多处理)来执行,例如,在程序的另一部分并行执行大量计算。

【讨论】:

  • 在 Python 中,多线程代码永远不会同时运行,因为 GIL 一次只能在线程上运行,只有在核心上才能与 python 线程一起使用。对于繁重的计算,最好使用Multiprocessing 模块。多处理将使用您 cpu 的所有核心。
  • 没错,感谢您指出这一点。我更新了答案以反映您的观点。
【解决方案2】:

我不明白你在问什么(关于“按顺序查找异步活动的代码”的部分),但由于没有答案,我会写一些想法。

让我们谈谈为什么我们需要 asyncio/threads。假设我们有一个任务要发出两个请求。

  1. 如果我们将使用普通的单线程非异步代码,我们唯一的选择 是请求一个 url 并且只有在它完成之后 - 对于 另一个:

    request(url1)
    request(url2)
    

    这里的问题是我们的工作效率低下:每个函数在执行的大部分时间里什么都不做,只是等待网络结果。如果我们能够以某种方式将 CPU 用于第二个请求,而第一个请求却卡在网络上并且不需要它,那将是很酷的。

  2. 这个问题可以通过在不同线程中运行函数来解决(通常也能解决):

    with ThreadPoolExecutor(max_workers=2) as e:
        e.submit(request, url1)
        e.submit(request, url2)
    

    通过这种方式,我们可以更快地获得结果。当第一个请求被网络卡住时,CPU 将能够为另一个线程中的第二个请求做一些有用的事情。

    然而,这不是理想的解决方案:线程之间的切换需要一些成本,执行流程比第一个示例更复杂。

    应该会有更好的方法。

  3. 使用一个函数空闲期开始执行另一个函数是 asyncio 的一般意义:

    await asyncio.gather(
        async_request(url1),
        async_request(url2),
    )
    

    事件循环管理执行流程:当第一个协程到达某个 I/O 操作并且 CPU 可以用于其他地方的工作时,第二个协程启动。稍后的事件循环返回以继续执行第一个协程。

    我们得到“并行”请求和清晰易懂的代码。由于我们在单线程中进行了并行化,因此我们不需要另一个。

实际上,当我们使用 asyncio 时,线程仍然很有用。如果我们愿意为他们付费,他们可以help我们快速将同步 I/O 函数转换为异步:

async def async_request(url):
    loop = asyncio.get_event_loop()
    return (await loop.run_in_executor(None, request, url))

但同样,它是可选的,我们通常可以找到模块来异步发出请求(和其他 I/O 任务)而无需线程。

当线程在异步程序中有用时,我没有遇到任何其他任务。

【讨论】:

  • 这是在算法交易的背景下,我使用 Inteactive 经纪人的 Python TWS API(如果我理解正确的话)在主代码之外的其他线程上进行回调。我是 python 新手,试图找出在环境中做事的最佳方法,并且对多线程和 asyncIO(在单线程中运行)之间的关系有点混淆。
猜你喜欢
  • 1970-01-01
  • 2010-09-26
  • 2011-07-03
  • 2015-03-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-31
  • 1970-01-01
相关资源
最近更新 更多