python / asyncio

asyncio historical repository
https://docs.python.org/3/library/asyncio.html
1.04k stars 177 forks source link

CoroWrapper in debug mode has incorrect throw method signature #429

Closed Bahus closed 8 years ago

Bahus commented 8 years ago

Hello!

When PYTHONASYNCIODEBUG is set asyncio wraps each coroutine in special CoroWrapperclass which has incorrect signature for throw method:

def throw(self, exc):
    return self.gen.throw(exc)

However it should be:

def throw(self, type, value=None, traceback=None):
    return self.gen.throw(type, value, traceback)

For example the problem appears when I'm using Tornado web-server with enabled asyncio debugging mode exception thrown in a coroutine causes another one:

Traceback (most recent call last):
  File ".../lib/python3.5/site-packages/tornado/web.py", line 1445, in _execute
    result = yield result
  File ".../lib/python3.5/site-packages/tornado/gen.py", line 1008, in run
    value = future.result()
  File ".../lib/python3.5/site-packages/tornado/concurrent.py", line 232, in result
    raise_exc_info(self._exc_info)
  File "<string>", line 3, in raise_exc_info
  File ".../lib/python3.5/site-packages/tornado/gen.py", line 1014, in run
    yielded = self.gen.throw(*exc_info)
  File "<string>", line 6, in _wrap_awaitable
TypeError: throw() takes 2 positional arguments but 4 were given

See tornado's code here.

Martiusweb commented 8 years ago

Hi,

Indeed, it seems that CoroWrapper.throw should have the same signature than generator.throw(): https://docs.python.org/3/reference/expressions.html#generator.throw However, the documentation doesn't say that it is possible to pass an exception instance if type is the only argument.

gvanrossum commented 8 years ago

Should be an easy fix. Just send a PR.

--Guido (mobile)

soar commented 7 years ago

What about fix for this problem?

1st1 commented 7 years ago

The change to fix this was committed a year ago, so Python 3.6 should have it fixed.

soar commented 7 years ago

I use tornado like this:

tornado.platform.asyncio.AsyncIOMainLoop().install()

loop = asyncio.get_event_loop()
loop.set_debug(True)

tornado_app = app.webapp.TornadoApp()
tornado_app.listen(8080)

loop.run_forever()

And any exception in tornado web request handler re-throws:

[E 170726 17:32:04 web:1590] Uncaught exception GET /r/1 (::1)
    HTTPServerRequest(...)
    Traceback (most recent call last):
      File "/home/soar/virtualenvs/v1/lib/python3.5/site-packages/tornado/web.py", line 1511, in _execute
        result = yield result
      File "/home/soar/virtualenvs/v1/lib/python3.5/site-packages/tornado/gen.py", line 1055, in run
        value = future.result()
      File "/home/soar/virtualenvs/v1/lib/python3.5/site-packages/tornado/concurrent.py", line 238, in result
        raise_exc_info(self._exc_info)
      File "<string>", line 4, in raise_exc_info
      File "/home/soar/virtualenvs/v1/lib/python3.5/site-packages/tornado/gen.py", line 1063, in run
        yielded = self.gen.throw(*exc_info)
      File "<string>", line 6, in _wrap_awaitable
    TypeError: throw() takes 2 positional arguments but 4 were given

Without loop.set_debug() - I see original exception as expected.

1st1 commented 7 years ago

What are the versions of Python and Tornado?

soar commented 7 years ago

Sorry, I've missed your first comment. Upgrading from python 3.5 to 3.6.2 solved my problem. Thank you, @1st1