循环中执行异步IO时PdfReader是否会导致API调用串行化失去异步效果?
问题解答
- 导致API调用串行的不是
PdfReader的处理逻辑,而是for循环中直接对process_pdf使用await的写法 - 你当前实现的
process_pdf本身就不满足异步IO要求,就算调整并发逻辑,底层调用依然会阻塞事件循环
串行原因详解
你当前的循环执行逻辑是严格按顺序执行的:
- 调用
await process_pdf(...),必须等待本次API调用完全返回结果,才会继续后续逻辑 - 执行
PdfReader读取、加页的同步计算逻辑 - 进入下一轮循环,才会发起下一次API调用
整个流程完全是串行的,100次API调用按顺序依次执行,和普通同步for循环效果一致。PdfReader只是await之后的普通同步操作,它本身不是导致串行的原因,就算删掉这部分逻辑,直接在循环里await process_pdf的写法依然是串行的。
现有异步实现的问题
你写的process_pdf虽然加了async关键字,但属于典型的伪异步实现:内部调用的transform_document_api没有加await,说明这是个同步阻塞的API调用。这种实现哪怕放在异步事件循环里运行,依然会卡住整个事件循环,没法实现异步IO的并发效果。如果要做真正的异步,你需要先把transform_document_api替换为异步HTTP客户端(比如aiohttp)实现的接口,调用时加上await。
正确异步并发写法示例
你可以先批量提交所有API请求,等所有结果返回后再统一处理PDF合并逻辑,参考代码:
import asyncio async def generate_pdf(self): # 批量创建所有异步任务,并发发起API请求 tasks = [process_pdf(self.xsl, xml_data) for _ in range(100)] # 等待所有API请求返回结果 all_data_bytes = await asyncio.gather(*tasks) # 统一处理PDF合并 for i, data_bytes in enumerate(all_data_bytes): pallet_pdf = PdfReader(fdata=data_bytes) pallet_pdf_output.addpage(pallet_pdf.getPage(i)) async def process_pdf(xsl, xml_data): # transform_document_api需替换为异步实现,调用时加await res_status, data_bytes = await async_transform_document_api(xml_data, xsl) return data_bytes
如果PdfReader相关处理逻辑耗时很高,担心阻塞事件循环,可以把这部分逻辑扔到线程池中运行。
内容的提问来源于stack exchange,提问作者evgenyorlov1
相关产品推荐
相关产品推荐

