Issue
Given the following program:
1 import asyncio
2 async def run():
3 try:
4 server = await asyncio.start_server(on_connected, '127.0.0.1', 15500)
5
6 async with server:
7 await server.serve_forever()
8 except:
9 print("exception!")
10
11 async def on_connected(reader, writer):
12 while True:
13 data = await reader.readline()
14 print(1 / 0)
15
16 asyncio.run(run())
When I run it, and use nc
to connect to it & send data, it will raise an exception in line 14
. However I am unable to handle it. Instead, I will get an exception printed and the program will hang.
nc
test:
$ nc localhost 15500
test
program output:
$ python3 serv
Task exception was never retrieved
future: <Task finished coro=<on_connected() done, defined at serv:14> exception=ZeroDivisionError('division by zero')>
Traceback (most recent call last):
File "serv", line 14, in on_connected
print(1 / 0)
ZeroDivisionError: division by zero
While I of course could just add a try/except
around line 14
, I want to implement a general exception handling which shall handle all errors which can ever occur inside of on_connected
.
How can I do this?
Solution
Asyncio provides a method to set a general exception handler
Let's apply it to this example:
- Let's just define our loop exception handler: handle_exception
- And inside this method let's manage exceptions. Next code just customize logging messages.
import asyncio
import logging
log = logging.getLogger(__name__)
async def run():
loop = asyncio.get_running_loop()
loop.set_exception_handler(handle_exception)
server = await asyncio.start_server(on_connected, '127.0.0.1', 5062)
async with server:
await server.serve_forever()
async def on_connected(reader, writer):
while True:
data = await reader.readline()
raise print(1 / 0)
def handle_exception(loop, context):
# context["message"] will always be there; but context["exception"] may not
msg = context.get("exception", context["message"])
if name := context.get("future").get_coro().__name__ == "on_connected":
if type(msg) == ZeroDivisionError:
log.error(f"Caught ZeroDivisionError from on_connected: {msg}")
return
log.info(f"Caught another minor exception from on_connected: {msg}")
else:
log.error(f"Caught exception from {name}: {msg}")
Output on this case is the following:
Caught ZeroDivisionError from on_connected: division by zero
Reference that I have used to look for further information:
- https://www.roguelynn.com/words/asyncio-exception-handling/ https://github.com/econchick/mayhem/blob/master/part-3/mayhem_2.py
Please, let me know if this answer your question.
Answered By - Angel Luis Blasco
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.