正在努力将使用ThreadPoolExecutors
的服务器查询工具的实现替换为使用 try {
assertTrue(hm.isPrime(-37337));
}
catch (AssertionError e ) {
e.printStackTrace();
}
和asyncio
的所有异步调用。由于网络调用是无阻塞的IO,因此大多数过渡都是直接的,保存响应使我感到困惑。
我正在使用的所有示例,甚至包括两个库的文档,都使用aiohttp
来收集所有等待的结果。就我而言,这些结果可以是许多GB范围内的文件,我不想将它们存储在内存中。
什么是解决此问题的合适方法?是否要使用asyncio.as_completed()
,然后:
asyncio.gather()
这不是引入线程吗(假设默认情况下我使用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)
),从而使它成为异步的多线程程序,而不是异步的单线程程序?
还有,这是否可以确保在任何时候仅将1个ThreadPoolExecutor
写入文件?我不希望对earliest_result
的调用正在运行,然后出现另一个结果,我尝试运行到同一文件;我想可以限制一个信号量。
答案 0 :(得分:1)
我建议使用aiohttp Streaming API。将您的响应直接写到磁盘而不是RAM上,并返回文件名而不是收集到响应本身。这样做根本不会占用太多内存。这是我的意思的一个小演示:
import asyncio
import aiofiles
from aiohttp import ClientSession
async def make_request(session, url):
response = await session.request(method="GET", url=url)
filename = url.split('/')[-1]
async for data in response.content.iter_chunked(1024):
async with aiofiles.open(filename, "ba") as f:
await f.write(data)
return filename
async def main():
urls = ['https://github.com/Tinche/aiofiles',
'https://github.com/aio-libs/aiohttp']
async with ClientSession() as session:
coros = [make_request(session, url) for url in urls]
result_files = await asyncio.gather(*coros)
print(result_files)
asyncio.run(main())
答案 1 :(得分:0)
就我而言,这些结果可能是许多GB范围内的文件,我不想将它们存储在内存中。
如果我是正确的,并且在您的代码中单个aws
意味着一个文件的下载,您可能会遇到以下问题:尽管as_completed
允许尽快将RAM中的数据交换到HDD您的aws
并行运行,同时将每个数据(带有部分下载文件的缓冲区)同时存储在RAM中。
要避免这种情况,您首先需要使用信号量以确保并行下载的文件不多,从而防止RAM过度使用。
这里是使用semaphore的示例。
这不是引入线程吗(假设我使用ThreadPoolExecutor 默认情况下),因此使它成为异步的多线程程序 异步的单线程程序?
我不确定,我理解您的问题,但是是的,您的代码将使用线程,但是在这些线程中仅执行save_result
。所有其他代码仍在单个主线程中运行。这里没什么问题。
还有,这是否确保只写入1个earlyest_result 随时归档吗?
是,是[*]。准确地说,在代码段的最后一行使用关键字await
可以确保:
_ = await loop.run_in_executor(None, save_result, earliest_result)
您可以将其读取为:“开始异步执行run_in_executor
,并在此行暂停执行流程,直到run_in_executor
完成并返回结果为止。”
[*]是的,如果您没有为f in as_completed(aws)
循环运行多个循环。