метод aiohttp ClientSession.get () завершается с ошибкой - Python3.7 - PullRequest
0 голосов
/ 07 февраля 2019

Я создаю небольшое приложение, которое пытается найти URL-адреса веб-сайта компании путем поиска их имен через Bing.Он принимает большой список названий компаний, использует API поиска Bing для получения первого URL-адреса и сохраняет эти URL-адреса в списке.

У меня проблема с aiohttp методом ClientSession.get(), в частности, он молча терпит неудачу, и я не могу понять почему.

Вот как я инициализирую скрипт.Следите за worker.perform_mission():

async def _execute(workers,*, loop=None):
    if not loop:
        loop = asyncio.get_event_loop()
    [asyncio.ensure_future(i.perform_mission(verbose=True), loop=loop) for i in workers]

def main():
    filepth = 'c:\\SOME\\FILE\\PATH.xlsx'
    cache = pd.read_excel(filepth)

    # CHANGE THE NUMBER IN range(<here>) TO ADD MORE WORKERS.
    workers = (Worker(cache) for i in range(1))
    loop = asyncio.get_event_loop()

    loop.run_until_complete(_execute(workers, loop=loop))

    ...<MORE STUFF>...

Метод worker.perform_mission() делает следующее (прокрутите вниз и посмотрите на _split_up_request_like_they_do_in_the_docs()):

class Worker(object):
    def __init__(self, shared_cache):
        ...<MORE STUFF>...

    async def perform_mission(self, verbose=False):
        while not self.mission_complete:
            if not self.company_name:
                await self.find_company_name()
                if verbose:
                    print('Obtained Company Name')
            if self.company_name and not self.website:
                print('Company Name populated but no website found yet.')
                data = await self.call_bing() #<<<<< THIS IS SILENTLY FAILING.
                if self.website and ok_to_set_website(self.shared_cache, self):
                    await self.try_set_results(data)
                    self.mission_complete = True
                else:
                    print('{} worker failed at setting website.'.format(self.company_name))
                    pass
            else:
                print('{} worker failed at obtaining data from Bing.'.format(self.company_name))
                pass

    async def call_bing(self):
        async with aiohttp.ClientSession() as sesh:
            sesh.headers = self.headers
            sesh.params = self.params
            return await self._split_up_request_like_they_do_in_the_docs(sesh)

    async def _split_up_request_like_they_do_in_the_docs(self, session):
        print('_bing_request() successfully called.') #<<<THIS CATCHES
        async with session.get(self.search_url) as resp:
            print('Session.get() successfully called.') #<<<THIS DOES NOT.
            return await resp.json()

И, наконец,мой вывод:

Obtained Company Name
Company Name populated but no website found yet.
_bing_request() successfully called.

Process finished with exit code 0

Может кто-нибудь помочь мне понять, почему print('Session.get() successfully called.') не срабатывает? ... или, может быть, помочь мне лучше задать этот вопрос?

1 Ответ

0 голосов
/ 07 февраля 2019

Взгляните на эту часть:

async def _execute(workers,*, loop=None):
    # ...
    [asyncio.ensure_future(i.perform_mission(verbose=True), loop=loop) for i in workers]

Вы создаете кучу задач, но не ожидаете, что эти задачи завершены.Это означает, что _execute само будет выполнено сразу после создания задач, задолго до их завершения.И так как вы запускаете цикл обработки событий до тех пор, пока не закончится _execute, он остановится вскоре после запуска.

Чтобы это исправить, используйте asyncio.gather , чтобы дождаться завершения нескольких ожидаемых:

async def _execute(workers,*, loop=None):
    # ...
    tasks = [asyncio.ensure_future(i.perform_mission(verbose=True), loop=loop) for i in workers]
    await asyncio.gather(*tasks)
...