4

I'm trying to catch exception thrown inside a run_until_complete but whatever I try, I can't seems to catch them properly.

Here's my latest attempt (note, I'm using Pypputeer, a fork of Puppeteer in Python, that uses asyncio):

import asyncio
from pyppeteer.launcher import launch

async def test(instance):
    page = await instance.newPage()
    await page.goto('http://www.google.com', {'waitUntil': 'load', 'timeout': 1})
    await page.pdf({'path': 'example.pdf'})


async def test2():
    instance = launch(headless=True)
    try:
        task = asyncio.ensure_future(test(instance))
        print(task)
        await task
    except:
        print("Caught!")

    instance.close()


def __main__():
    try:
        loop = asyncio.new_event_loop()
        asyncio.set_event_loop(loop)
        loop.run_until_complete(test2())
    except:
        print("ERROR")
    return 'ok'

The issue I'm having with this code, is two fold:

  1. if I do asyncio.get_event_loop instead, I get the following error:

There is no current event loop in thread 'Thread-1'. 2. If I change the timeout to a decent value, I get the following error (at loop.run_until_complete(test2())): RuntimeError: This event loop is already running 3. If I set the timeout to 1 (to force the error), I get the exception indicated below, shown in the console, and the text "ERROR" is shown. (but not caught).

Here's the stacktrace:

Exception in callback NavigatorWatcher.waitForNavigation.<locals>.watchdog_cb(<Task finishe...> result=None>) at /home/user/www/project/api/env/lib/python3.6/site-packages/pyppeteer/navigator_watcher.py:49
handle: <Handle NavigatorWatcher.waitForNavigation.<locals>.watchdog_cb(<Task finishe...> result=None>) at /home/user/www/project/api/env/lib/python3.6/site-packages/pyppeteer/navigator_watcher.py:49>
Traceback (most recent call last):
  File "/usr/lib64/python3.6/asyncio/events.py", line 145, in _run
    self._callback(*self._args)
  File "/home/user/www/project/api/env/lib/python3.6/site-packages/pyppeteer/navigator_watcher.py", line 52, in watchdog_cb
    self._timeout)
  File "/home/user/www/project/api/env/lib/python3.6/site-packages/pyppeteer/navigator_watcher.py", line 40, in _raise_error
    raise error
concurrent.futures._base.TimeoutError: Navigation Timeout Exceeded: 1 ms exceeded

So, TLDR, how can I catch exceptions thrown inside a run_until_complete call of asyncio?

halfer
  • 19,824
  • 17
  • 99
  • 186
Cyril N.
  • 38,875
  • 36
  • 142
  • 243

1 Answers1

1

You can't catch this error because it doesn't happen somewhere before event loop finished it's work:

loop.run_until_complete(test2())
print('TEST !!!')  # You will see this line, because there was no exception before

But if you look at whole traceback you will see:

Error in atexit._run_exitfuncs:

It means exception happens inside one of the functions Pypputeer registered using atexit handler. You should search how to catch exception there, but I'm not sure if it's possible.

If an exception is raised during execution of the exit handlers, a traceback is printed (unless SystemExit is raised) and the exception information is saved. After all exit handlers have had a chance to run the last exception to be raised is re-raised.


Not related, but never do such thing.

except:
Mikhail Gerasimov
  • 36,989
  • 16
  • 116
  • 159
  • Thank you for your help. On the side note, the `except` was just to speed things up here. Since it's said "After all exit handlers have had a chance to run the last exception to be raised is re-raised.", wouldn't it be possible to catch it? – Cyril N. Feb 28 '18 at 08:49
  • @CyrilN.I googled a bit before posting answer and couldn't find a solution. But I can't say I'm sure there isn't one. – Mikhail Gerasimov Feb 28 '18 at 08:56