Как сказано в названии - у меня проблема с асинхронным материалом. То, чего я пытаюсь достичь, написано под каждой функцией. К сожалению, в этом состоянии кода я получаю сообщение об ошибке:
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()
Ваша проблема заключается в неправильном использовании указанной ниже переменной resp.content
.
async def task(session, item, urls):
async with session.get(item) as resp:
image_bytes = BytesIO(await resp.content)
См. Документацию aiohttp потоковая передача содержимого ответа.
While methods
read()
,json()
andtext()
are very convenient you should use them carefully. All these methods load the whole response in memory. For example if you want to download several gigabyte sized files, these methods will load all the data in memory. Instead you can use thecontent
attribute. It is an instance of theaiohttp.StreamReader
class. The gzip and deflate transfer-encodings are automatically decoded for you:async with session.get('https://api.github.com/events') as resp: await resp.content.read(10)
Вы также можете
BytesIO
- используйте io.BytesIO(await resp.read())
(см. содержимое двоичного ответа.)Здравствуйте, большое спасибо за объяснение! Я вроде как ожидал, что тут же возникнет проблема, и, вероятно, слишком устал, чтобы осознавать это. Потом я заметил, что у меня все равно больше проблем с кодом, ха-ха :))
Предоставление минимальный воспроизводимый пример приведет к тому, что больше людей захотят помочь.