Search code examples
pythonexceptionsocket.iotry-catchpython-asyncio

In python how to catch all and every exception and error ever thrown anywhere


So, I'm familiar with try-except, however in this case it's not working. I have a package, that uses socketio and asyncio. The connection is done inside an asyncio task. If the it cannot connect to the server, it throws an exception of course. What I wanted to do, is wrap the code that uses this function in a try-except block, thinking that it will catch the exception thrown inside the package, but it's not working at all: The exceptions are thrown, and the except block does not catch them.

The relevant code looks like this:

async def main():
    config = configparser.ConfigParser()
    # print(os.path.dirname(sys.executable))
    path = str(os.path.dirname(os.path.abspath(__file__))) + "/config.ini"
    print(path)
    config.read(path) 
    servers = config["WIREGUARD_SERVER"]["URLS"].split(",")
    status = None
    while status != "Connected":
        for server in servers:
            print("\ntrying to connect to server: "+server)
            try:
                something = await MySomething("client", server)
            except:
                print("Could not connect to server at: "+server)
                await asyncio.sleep(2)
        

loop = asyncio.new_event_loop()
loop.create_task(main())
loop.run_forever()

So my question is how can I catch every exception and error ever thrown inside the program? Sadly, rewriting the package is not an option


Solution

  • It is very hard to find a solution to help you since you did not provide a reproducible example of your problem. (Just implement the MySomething above in a way it raises the out-of-band exeception you are trying to catch, and maybe we can come with a workaround.)

    But in short, the answer for In python how to catch all and every exception and error ever thrown anywhere? is: there is no way.

    Sorry, there is no "universal exception hook" - an exception simply propagates on the Python Frames where it occurred until it is caught with an Except clause, or the root frame (which can be in a separate thread) is met. Moreover, exceptions taking place inside __del__ methods also do not propagate.

    In particular: if an exception takes place, and it is handled in code surrounding it which you called, there is no way for your caller code to know about the nested exception at all.

    For uncaught exceptions there are three ways of checking, besides a try/except block:

    An uncaught exception in the main thread and interpreter will eventually stop the interpreter and print a traceback. One can creat e a hook to catch such an uncaught exception by using sys.excepthook (https://docs.python.org/3/library/sys.html#sys.excepthook) - but I don't think that can help you (your except block would catch such an exception before it would reach the main ExceptHook)

    If it takes place in another thread, you can set threading.excepthook to a handler function of yours, and detect exceptions (but whatever code was running in that thread will be unrecoverable by the point this hook is reached anyway).

    Also, exceptions taking place in asynchronous code are annotated, and can be inspected when checking the faulty tasks results, by calling a task exception() method (https://docs.python.org/3/library/asyncio-future.html#asyncio.Future.exception ).

    There is another kind of Python event called "Audit Hooks", introduced in Python 3.8 - they could've been made to enable tracing exceptions whenever they occur, even if they are handled - but it was not done so: there are no audit hook events triggered by exceptions.

    So, the means above are all that is possible, apart from enabling tracing (with sys.settrace https://docs.python.org/3/library/sys.html#sys.settrace ) - and run all your target code in a supervised way, as if your code is a debugger. Code running in this way is slow, and certainly cannot be used in production - still, it would be possible to locate the exceptions where they take place by using this.