куда мне добавить еще одно ожидание, чтобы asyncio работал правильно? - PullRequest
0 голосов
/ 25 апреля 2019

Я загружаю все изображения с pexels.com с заданной клавиатурой пользователя.Программа выдает мне следующую ошибку:

Traceback (most recent call last):
File "./asyncioPexels.py", line 73, in <module>
asyncio.run(forming_all_pages(numberOfPages, mainurl))
File "/usr/lib/python3.7/asyncio/base_events.py", line 573, in run_until_complete
return future.result()
File "./asyncioPexels.py", line 50, in forming_all_pages
await download_all_pages(urls)
File "./asyncioPexels.py", line 38, in download_all_pages
async with aiohttp.ClientSession as session:
AttributeError: __aexit__

Я думаю, что проблема сейчас в том, что я использую функцию download_all_pages в качестве менеджера контекста!Если это проблема, как я должен это исправить?У меня есть общая идея, чтобы заставить его работать как менеджер контекста, или есть более простое решение?Вот весь мой код:

async def download_single_image(subsession, imgurl):
    print(f'Downloading img {imgurl}')
    async with session.get(imgurl) as res:
        imgFile = open(os.path.join(str(keyword), os.path.basename(imgurl)), 'wb')
        for chunk in res.iter_content(100000):
            imgFile.write(chunk)
        imgFile.close()

async def download_all_images(imgurls):
    async with aiohttp.ClientSession as subsession:
        subtasks = []
        for imgurl in imgurls:
            subtask = asyncio.ensure_future(download_single_image(subsession, imgurl))
            subtasks.append(subtask)
        await asyncio.gather(*subtasks, return_exception=True)

async def download_single_page(session, url):
    print(f'Downloading page {url}...')
    imgurls = []
    async with session.get(url) as response:
        imgs = response.text.split('infiniteScrollingAppender.append')[1:]
        for img in imgs:
            soup = BeautifulSoup(img[2:-5].replace("\\'", "'").replace('\\"', '"'), 'html.parser')
            imgurls.append(soup.select('.photo-item__img')[0].get('srcset'))
        await download_all_images(imgurls)

async def download_all_pages(urls):
    async with aiohttp.ClientSession as session:
        tasks = []
        for url in urls:
            task = asyncio.ensure_future(download_single_page(session, url))
            tasks.append(task)
        await asyncio.gather(*tasks, return_exception=True)

async def forming_all_pages(numberOfPages, mainurl):
    urls = []
    for _ in range(1, numberOfPages + 1):
        page = mainurl + str(_)
        urls.append(page)
    await download_all_pages(urls)    

if __name__ == "__main__":
    asyncio.run(forming_all_pages(numberOfPages, mainurl))

Как решить эту проблему для запуска кода?

1 Ответ

0 голосов
/ 25 апреля 2019

В forming_all_pages у вас есть

download_all_pages(urls)

Но, как говорит исключение,

./asyncioPexels.py:50: RuntimeWarning: coroutine 'download_all_pages' was never awaited

Измените это на

await download_all_pages(urls)

Вам также нужно изменить download_single_page, чтобы использовать

await download_all_images(imgurls)

Наконец, forming_all_pages должно быть ожидаемым. Вам нужно изменить его на

async def forming_all_pages(numberOfPages, mainurl):
...