Python异步代码运行.py文件报await only allowed in async function错误
报错根因
这个报错和自定义read_blob()方法是否标记async无关,触发错误的是脚本最后一行全局作用域里的await调用:
- 原生Python语法明确规定:
await关键字仅允许在被async标记的函数/方法内部使用,模块顶层的全局作用域不属于async函数范围,直接写await就会抛出该错误。 - Jupyter Notebook的IPython内核做了特殊兼容,会自动给每个单元格的代码包裹异步运行上下文,所以顶层直接写
await可以正常运行,但这不是Python原生支持的写法,放到普通.py文件里执行就会报错。 - 原代码还存在一个隐含问题:使用了
pd.read_parquet但没有导入pandas库,修复语法报错后运行也会触发NameError。
修复方案
写正式.py脚本时,需要把顶层的异步逻辑封装到async入口函数里,通过asyncio.run()启动事件循环执行,同时补全缺失的导入、用完异步客户端后主动释放连接:
# 补全缺失的pandas导入 import pandas as pd from azure.storage.blob.aio import ContainerClient import asyncio from azure.core.exceptions import ResourceNotFoundError from io import BytesIO class AsyncContainerClient(ContainerClient): async def read_blob(self, blob_name: str, add_blob_name_col=False, add_blob_date_col=False, preprocessing_func=None, zip_regex=r'.+\.gz$', csv_regex='.+\.csv(\.gz)?$', parquet_regex='.+\.parquet$', regex_string=None, **kwargs): assert isinstance(blob_name, str), f'{blob_name} is not a string' try: blob = await self.download_blob(blob_name) with BytesIO() as byte_stream: await blob.readinto(byte_stream) byte_stream.seek(0) return pd.read_parquet(byte_stream, engine='pyarrow') except ResourceNotFoundError: return 0 async def main(): blob_sas_url = "https://proan.blob" acc = AsyncContainerClient.from_container_url(blob_sas_url) test_dirs = ["models1/model.parquet", "models2/model.parquet", "models3/model.parquet"] res = await asyncio.gather(*(acc.read_blob(f) for f in test_dirs)) # 此处添加res的后续处理逻辑 print(res) # 用完异步客户端主动关闭,释放连接资源 await acc.close() if __name__ == "__main__": asyncio.run(main())
补充说明
如果是在Python 3.8+的原生交互式命令行环境中,可以执行python -m asyncio启动支持顶层await的交互模式,该模式下可以直接在全局作用域写await,但该方式仅适用于交互式调试场景,正式脚本仍需使用上述asyncio.run()的入口写法。
内容的提问来源于stack exchange,提问作者user9532692
相关产品推荐
相关产品推荐

