将Web响应写到异步程序中的文件

pst*_*tix 5 python asynchronous python-3.x python-asyncio aiohttp

致力于ThreadPoolExecutors使用asyncio和替换所有异步调用所使用的服务器查询工具的实现aiohttp。由于网络调用是非阻塞IO,因此大多数过渡都是直接的,保存响应使我感到困惑。

我正在使用的所有示例,甚至是两个库的文档,都使用该示例asyncio.gather()来收集所有等待的结果。就我而言,这些结果可以是许多GB范围内的文件,我不想将它们存储在内存中。

什么是解决此问题的合适方法?是否可以使用asyncio.as_completed()然后:

for f in as_completed(aws):
    earliest_result = await f
    # Assumes `loop` defined under `if __name__` block outside coroutine
    loop = get_event_loop()
    # Run the blocking IO in an exectuor and write to file
    _ = await loop.run_in_executor(None, save_result, earliest_result)
Run Code Online (Sandbox Code Playgroud)

这不是引入线程(假设ThreadPoolExecutor默认情况下使用a ),从而使它成为异步多线程程序,而不是异步单线程程序吗?

此外,这是否可以确保earliest_result在任何时候仅将1 写入文件?我不想await loop.run_in_executor(...)运行该调用,然后出现另一个结果,我尝试运行到同一文件;我想可以限制一个信号量。

Mik*_*mov 0

就我而言,这些结果可以是许多 GB 范围内的文件,并且我不想将它们存储在内存中。

如果我是正确的并且在您的代码中单个aws意味着下载单个文件,您可能会面临以下问题:虽然as_completed允许尽快将数据从 RAM 交换到 HDD,但所有aws运行的并行存储每个数据(带有部分下载的文件的缓冲区) )同时在RAM中。

为了避免这种情况,您需要使用信号量来确保首先不会并行下载太多文件,从而防止 RAM 过度使用。

这是使用信号量的示例。

这是否会引入一个线程(假设我默认使用 ThreadPoolExecutor),从而使其成为异步、多线程程序而不是异步、单线程程序?

我不确定,我理解你的问题,但是是的,你的代码将使用线程,但只会save_result在这些线程内执行。所有其他代码仍然在单个主线程中运行。这里没什么不好的。

此外,这是否可以确保任何时候只有 1 个 Early_result 被写入文件?

是的[*]。准确地说,await您的代码片段最后一行的关键字将确保它:

_ = await loop.run_in_executor(None, save_result, earliest_result)
Run Code Online (Sandbox Code Playgroud)

您可以将其解读为:“开始run_in_executor异步执行并在此行暂停执行流程,直到run_in_executor完成并返回结果”。


f in as_completed(aws)[*] 是的,如果您一开始就没有并行运行多个 for循环。