在我的Python控制台应用程序中,我有一个简单的for循环,如下所示:
for package in page.packages:
package.load()
# do stuff with package
每次调用时,package.load()
都会发出一系列HTTP请求。由于page.packages
通常包含数千个软件包,load()
调用正成为我的应用程序的一个重要瓶颈。
为了加快速度,我考虑过使用multiprocessing
模块进行并行化,但这仍然会浪费大量资源,因为线程是网络绑定的,而不是CPU绑定的:有1个线程无所事事,你有4个。是否可以使用异步而不是以某种方式使用一个/几个线程,但确保他们永远不会等待网络?
答案 0 :(得分:4)
asyncio非常适合这种情况,但您需要使用类似aiohttp的方式将HTTP加载代码Package.load
转换为异步。例如:
async def load(self):
with self._session.get(self.uri, params) as resp:
data = resp.read() # etc
您之前使用的顺序循环将表示为:
async def load_all_serial(page):
for package in page.packages:
await package.load()
但现在您还可以选择并行启动下载:
async def load_all_parallel(page):
# just create tasks, do not await them yet
tasks = [package.load() for package in page.packages]
# now let them run, and wait until all have been completed
await asyncio.gather(*tasks)
从同步代码调用这些异步函数中的任何一个都非常简单:
loop = asyncio.get_event_loop()
loop.run_until_complete(load_all_parallel(page))