Python code that should contain an error from asyncio.wait and be caught in a try clause is not caught

so I have an event loop that will run_until_complete my accept_connection method

 @asyncio.coroutine def accept_connection(self): assert self.server_socket is not None while True: client, addr = yield from self.loop.sock_accept(self.server_socket) asyncio.async(self.handle_connection(client, addr)) 

My handle_connection method is as follows

  def handle_connection(self, client, addr): #removed error checking while True: try: yield from asyncio.wait([con.handle_read_from_connection()], timeout=5.0) except (AssertionError, PacketException): print("Invalid packet detected!") 

Finally, my handle_read_from_connection (currently) looks like this:

 @asyncio.coroutine def handle_read_from_connection(self): raise PacketException("hello") 

therefore, this method should always raise an error and remove the exception block from the try catch statement and output an invalid package. Instead, I get a trace!

 future: Task(<handle_read_from_connection>)<exception=PacketException('hello',)> Traceback (most recent call last): File "/usr/lib/python3.4/asyncio/tasks.py", line 283, in _step result = next(coro) File "/some_path.py", line 29, in handle_read_from_connection raise PacketException("hello") GameProtocol.GameProtocol.PacketException: hello 

Does anyone know what is going on here? Why does the catch attempt not work? and how can I get it so we can catch these errors.

+7
python try-catch python-asyncio
source share
1 answer

You need to use the return values ​​from asyncio.wait() :

 import asyncio class Error(Exception): pass @asyncio.coroutine def main(): try: done, pending = yield from asyncio.wait([raise_exception()], timeout=1) assert not pending future, = done # unpack a set of length one print(future.result()) # raise an exception or use future.exception() except Error: print('got exception', flush=True) else: print('no exception', flush=True) @asyncio.coroutine def raise_exception(): # normally it is a generator (yield from) # or it returns a Future raise Error("message") loop = asyncio.get_event_loop() loop.run_until_complete(main()) loop.close() 

Exit

 got exception 

The current implementation of asyncio.coroutine assumes that if the function is not a generator (as in your case), then it returns the future, and therefore it should be converted to a generator, so calling raise_exception() does not raise an exception, because it just creates an object- generator (coroutine).

Then asyncio.wait() gives it, and some equivalent of future.set_exception(exception) is executed.

To avoid the error you see; you need to use the exception either by directly calling future.result() or future.exception() .

+7
source share

All Articles