Python 什么时候使用asyncio没有意义?

Python 什么时候使用asyncio没有意义?,python,multithreading,asynchronous,concurrent.futures,Python,Multithreading,Asynchronous,Concurrent.futures,在什么情况下,一个线程或执行器(使用线程)将通过asyncio 随着我使用Python(CPython)的经验的发展,它集中于优化工作中的脚本,以批量执行某种形式的web服务调用和流程响应。然而,经过几代脚本构建之后,我发现自己在想为什么我永远不会使用最新的脚本 请允许我在下面提供一些上下文 问题:从服务器A向客户端B请求N个文件,处理并保存到磁盘 依次 构建请求容器,发送单个请求,处理响应,重复直到完成 可能被认为是“标准/初学者”方法,因为它是直观达到的 多线程 再次构建容器,但同时发

在什么情况下,一个线程或执行器(使用线程)将通过
asyncio

随着我使用Python(CPython)的经验的发展,它集中于优化工作中的脚本,以批量执行某种形式的web服务调用和流程响应。然而,经过几代脚本构建之后,我发现自己在想为什么我永远不会使用最新的脚本

请允许我在下面提供一些上下文

问题:从服务器A向客户端B请求N个文件,处理并保存到磁盘

  • 依次

    • 构建请求容器,发送单个请求,处理响应,重复直到完成
    • 可能被认为是“标准/初学者”方法,因为它是直观达到的
  • 多线程

    • 再次构建容器,但同时发送多个请求
    • 使用信号量限制活动连接
    • 使用队列在工作人员和转储响应之间共享
    • 让主线程处理响应
    • 从本质上讲,工作人员是“火”和“忘”,主要在循环检查队列中运行数据
    • 将关注点与仅处理数据的主关注点分开
  • 线程池执行器

    • 本质上类似于解决方案2,只是代码行少了很多
    • 推理:“我希望能够在收到回复后尽快处理”
    • 不需要队列和信号量的显式实例化
    • 如果没有弄错,在
      as_completed()
    • 大致轮廓
  • 异步

    • 这里引入了一个严重的混淆,但基本上理解了这个概念
    • 与解决方案2和3不同,它在单个线程上运行
    • 除了写入磁盘之外,在实现中更接近(非常接近)解决方案3
    • 需要使用解决方案3组件通过
      run\u in\u executor()保存到磁盘
  • 因此,我们陷入了我目前的困境:为什么我总是想使用
    asyncio
    进行I/O绑定的工作

    异步编程是一个非常类似OOP的概念,解决方案3的文档甚至说“异步执行可以通过线程执行”。但是,如果我可以在单个线程上实现异步执行(不包括阻止I/O到磁盘的额外线程),为什么我要使用解决方案1-3呢

    我知道,考虑到GIL,CPython多线程是次优的;不管怎样,我看不出任何人会再使用线程或执行器的理由。我在谷歌上搜索了一段时间,想看看是否能找到一篇好文章来说明为什么人们更愿意使用它们,但我只找到了一些文章来说明为什么线程(以及随后使用线程的执行器)是坏的:上下文切换(GIL/OS)、竞争条件、资源匮乏等等

    由于CPython不使用线程来利用多核cpu(我相信这就是
    多处理
    库),线程不用于繁重的计算任务;因此,为了提高性能,将它们限制为I/O绑定的操作。然而,这并没有给我足够的理由去理解为什么线程或执行器会在
    asyncio
    上使用


    如果您可以在一个线程(可能2-3)中完成所有任务,那么为什么还要继续引入创建、管理和销毁线程的开销(包括显式的和通过池/执行器)?

    我认为多线程和异步IO之间的决定实际上就是您需要哪种类型的多任务处理。如果程序中的一切都在您的控制之下,那么异步IO/多处理可能始终是正确的选择。然而,也许你想开始一项任务,其中抢先多任务是正确的选择。例如,在第三方库中启动任务。使用线程的一个明显原因是库不支持异步IO。然而,即使它支持asyncio,您也可能不希望相信该库能够根据需要随时控制您的任务。然后,您可以使用另一个运行该代码的asyncio事件循环启动一个新线程


    因此,我认为真正的问题是:何时使用协作式多任务处理,何时使用抢占式多任务处理。

    我认为多线程和异步IO之间的决定实际上是您需要哪种类型的多任务处理。如果程序中的一切都在您的控制之下,那么异步IO/多处理可能始终是正确的选择。然而,也许你想开始一项任务,其中抢先多任务是正确的选择。例如,在第三方库中启动任务。使用线程的一个明显原因是库不支持异步IO。然而,即使它支持asyncio,您也可能不希望相信该库能够根据需要随时控制您的任务。然后,您可以使用另一个运行该代码的asyncio事件循环启动一个新线程

    所以我认为真正的问题是:什么时候使用协作,什么时候使用先发制人的多任务处理