so I have an event loop which 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 looks like this
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 hit the except block of the try catch statement and print invalid packet detected. Instead what happens is I get a traceback!
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 going on here? why is the try catch not working? and how can I get it so we can catch these errors
You need to use the returned 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()
got exception
The current implementation of asyncio.coroutine
assumes that if a function is not a generator (like in your case) then it returns a Future and thus it should be converted to be a generator therefore calling raise_exception()
doesn't raise an exception because it just creates the generator object (the coroutine).
Then asyncio.wait()
yields it and some equivalent of future.set_exception(exception)
is done.
To avoid the error output that you see; you need to consume the exception either by calling future.result()
or future.exception()
directly.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With