【问题标题】:Will asyncio help me here?asyncio 会在这里帮助我吗?
【发布时间】:2018-07-05 20:35:13
【问题描述】:

我有一个使用 wxpython4.0.3 开发的小 Python 应用程序,它执行一个相当简单的 ETL 类型任务:

  • 接受用户输入以选择包含多个 包含 CSV 文件(时间序列数据)的子目录。
  • 转换每个文件中的数据以符合格式 第三方收件人要求并将其写入新的 文件。
  • 将每个新文件压缩成一个以原始文件命名的文件 文件的父目录
  • 在用户的倡议下,应用程序然后将 zip 文件通过 FTP 发送到 要加载到数据存储中的第三方。

该应用程序运行良好,但处理数千个 CSV 文件所需的时间非常极端,据我所知主要是 IO 限制。

asyncio 是否是一个合理的选择,或者是否有其他任何人都可以提出的建议?我最初将它作为 CLI 编写,并通过使用 pypy 看到了显着的性能提升,但是当我为其他人开发 UI 时,我不愿意将 pypy 与 wxpython 结合起来。

感谢您的指导。

【问题讨论】:

  • 为什么您认为它主要受 I/O 限制? PyPy 显着加速这一事实意味着可能需要加速大量 CPU 密集型工作。

标签: python wxpython python-asyncio


【解决方案1】:

如果您看到使用 PyPy 而不是 CPython 显着加速,这意味着您的代码可能没有 I/O 绑定。这意味着使 I/O 异步不会有太大帮助。另外,这也将是额外的工作,因为您必须将所有 CPU 密集型任务重组为可以重复 await 的小块,这样它们就不会阻塞其他任务。

所以,您可能想在这里使用多个进程。

最简单的解决方案是使用concurrent.futures.ProcessPoolExecutor:只需将任务扔给执行程序,它就会在子进程上运行它们并返回Future

与使用asyncio 不同,您根本不需要更改这些任务。他们可以通过循环 csv 模块来读取文件,在一个大块中处理它,甚至使用同步的 ftplib 模块,而无需担心任何人会阻止其他人。只有您的顶级代码需要更改。

但是,您可能需要考虑将代码拆分为在 CPython 中运行的 wx GUI,以及在 PyPy 中通过 subprocess 运行的多处理引擎,然后将 PyPy 中的 ProcessPoolExecutor 分离为好。这需要更多的工作,但这意味着您将获得使用 PyPy 的 CPU 优势、使用 CPython 的经过良好测试的 wx 优势以及多处理的并行性。

另一个需要考虑的选择是引入像 NumPy 或 Pandas 这样的库,它们可以更快地完成慢速部分(无论是读取和处理 CSV,还是对数千行进行某种元素计算,等等)(并且甚至可能发布 GIL,这意味着您不需要多处理)。


如果您的代码确实 I/O 绑定代码,并且主要绑定在 FTP 请求上,asyncio 会有所帮助。但这需要重写大量代码。您需要找到或编写一个asyncio 驱动的FTP 客户端库。而且,如果文件读取占用了您大部分时间,那么将其转换为异步就更难了。

还有将wx 事件循环与asyncio 事件循环集成的问题。您可能能够在第二个线程中运行asyncio 循环,但随后您需要想出某种方式在主线程中的wx 事件循环和asyncio 循环之间进行通信后台线程。或者,您可能能够从另一个循环驱动一个循环(或者甚至可能有第三方库为您执行此操作)。但是使用twisted 而不是asyncio 之类的东西(或有更好的第三方库来帮助)可能会容易得多。

但是,除非您需要大量并发(您可能不需要,除非您有数百个不同的 FTP 服务器可以与之通信),线程应该也能正常工作,对代码的更改要少得多。只需使用concurrent.futures.ThreadPoolExecutor,这与使用ProcessPoolExecutor 几乎相同,如上所述。

【讨论】:

  • 但是为什么是 ThreadPoolExecutor?如果瓶颈是数据处理,则由于 GIL 将无济于事。那么 ProcessPoolExecutor 呢?
  • @MikhailGerasimov OP 说代码是 I/O 绑定的。如果他是对的,那么 GIL 就不是问题,线程可以正常工作。如果他错了……好吧,这就是我回答的前半部分的内容。
  • @MikhailGerasimov 啊,刚刚意识到我的链接和文字是落后的。这让你感到困惑吗? (即使没有,我相信它会让其他读者感到困惑,所以我修复了它,感谢您让我看到它。)
【解决方案2】:

是的,您可能会从使用异步库中受益。由于您的大部分时间都花在等待 IO 上,因此编写良好的异步程序将使用该时间来做其他事情,而不会产生额外线程/进程的开销。它会很好地扩展。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-05-23
    • 1970-01-01
    • 1970-01-01
    • 2023-04-08
    • 2022-01-06
    • 1970-01-01
    • 2021-03-24
    相关资源
    最近更新 更多