【问题标题】:Python - getting lost around asyncPython - 在异步中迷失方向
【发布时间】:2021-06-25 22:34:20
【问题描述】:

正如标题所说 - 我遇到了异步问题。我要实现的目标是写在每个函数下。可悲的是,在这种代码状态下,我得到了错误:

TypeError: object StreamReader can't be used in 'await' expression 最后是RuntimeError: Event loop is closed

我在谷歌上搜索了一段时间,并没有真正找到适合我的东西的解决方案。有没有人可以帮助我并弄清楚我做错了什么?我可以在一个异步函数中使用 2x async with .. 吗?

谢谢!

 
def load_file(file_path):
    with open(file_path, "r") as f:
        content = f.readlines()
        content = [a.strip() for a in content]
    return content

### --> Getting list of urls

async def task(session, item, urls):
    async with session.get(item) as resp:
        image_bytes = BytesIO(await resp.content)

### --> Downloading the image and getting image bytes

    async with session.post(
        TORCH_URL, data=image_bytes, headers={"authorization": TOKEN}
    ) as resp:
        response = await resp.json()
        print(response)

### --> Sending the image bytes to an API and getting a little json file as a response 

async def asyncmain(urls, path, content):

    tasks = []
    async with aiohttp.ClientSession() as session:
        tasks = [task(session, url, urls) for url in content]
        await asyncio.gather(*tasks)

### --> Gathering the tasks with .gather()

@click.command()
@click.option("--urls", "-u", is_flag=True, help="Use this if you have urls")
@click.option(
    "--path",
    "-p",
    help="Path to file with variant IDs, can be combined with -u (having urls in file)",
)
def main(urls, path):
    tasks = []
    content = load_file(path)
    asyncio.run(asyncmain(urls, path, content), debug=True)

### --> Fire asyncio.run with some params

if __name__ == "__main__":
    main()

【问题讨论】:

标签: python async-await python-asyncio aiohttp


【解决方案1】:

您的问题是下面的resp.content 变量使用不当。

async def task(session, item, urls):
    async with session.get(item) as resp:
        image_bytes = BytesIO(await resp.content)

请参阅 aiohttp 的 streaming response content 文档。

虽然read()json()text() 方法非常方便,但您应该谨慎使用它们。所有这些方法都将整个响应加载到内存中。例如,如果您要下载几个千兆字节大小的文件,这些方法将加载内存中的所有数据。相反,您可以使用 content 属性。它是aiohttp.StreamReader 类的一个实例。 gzip 和 deflate 传输编码会自动为您解码:

async with session.get('https://api.github.com/events') as resp:
    await resp.content.read(10)

你可以

  • (a) 下载块并将它们存储到磁盘中,或者
  • (b) 如果二进制文件不大并且可以存储到内存中——根据您使用BytesIO 似乎是这种情况——使用io.BytesIO(await resp.read())(参见binary response content。)

【讨论】:

  • 您好,非常感谢您的解释!我有点期待那里有问题,我可能太累了,没有意识到这一点。然后我注意到我在代码中还有更多问题哈哈:))
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-09-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多