I have had multiple cases where i need to exit from the interpreter cleanly in its entirety (threads included).
the problem is critical errors (because they are not expectations, but is networking related) , that i cant catch, and if i sys.exit another module with catch it , because that specific module caches in every function it has.
i dont want to use os._exit() because that is not clean
You are not in control of the application. Raise an exception; if the caller catches it, that’s clearly because they intend to handle it. And if they catch it and don’t handle it, that’s not your fault - it’s a buggy application.
On the other hand, if you’re in control of the application, and it’s doing this, then fix the application - it’s buggy.
How is this other module catching your exceptions?
What is the relationship between your module, the other module, and the main program running? Who owns the threads you want to kill?
The correct way to fail from a critical error in a module is to raise an exception. If the main application catches and suppresses that error, that’s not your business. If they call your module again, then if the error state persists, you raise the exception again. Its not your problem if the application keeps going.
Trying to kill the main application is rude and should only be allowed for the most severe failures that corrupt the entire program state, not just one module. E.g. if your module dumps me out of the interactive interpreter with no possibility of catching the exception, you better believe I’ll be dumping your module into the trash.
Can you be more specific about what it is about os._exit() you don’t like? If there are threads, it’s the only way to exit the program, “cleanly” or otherwise.
From the operating system’s perspective, os._exit() cleanly exits the process, freeing all memory and closing all file descriptors.
the threads are mine, unless the main program makes one.
its not an exception, its an error that cant be handled because its a bug that wont be fixed on a remote server. im writing a lib that connects with that server. if the server runs into this bug, then that user cant continue running at all.
edit: here is a snipit to show the error that breaks the entire script
elif listener == "__meowerbot__login":
if status == "E:104 | Internal": # sever sends this when it cant kick a shadow client
requests.post("https://webhooks.meower.org/post/home", json={"post": "ERROR: MeowerBot.py Webhooks Logging\n\n Account Softlocked.", 'username': self.username})
print("CRITICAL ERROR! ACCOUNT SOFTLOCKED!!!!.", file=sys.__stdout__)
sys.exit(1) # waiting for https://discuss.python.org/t/a-way-to-exit-cleanly-without-the-possibility-of-caller-catching-it/22442/2
Once you detect the error raise a exception so that the caller can decide what to do with the error.
Document what is happening so the caller has the background facts.
Not sure what you mean by a “client module”, but if you have a library that connects to a remote server, it is MINDBOGGLINGLY RUDE to terminate the entire process when you get a problem on that remote server. So if you’re going to do this, make sure you put a big warning at the top of your documentation:
CAUTION: This module will abruptly terminate YOUR ENTIRE APPLICATION if the account gets softlocked. Be sure to avoid using this module. Like, ever.
You must have a way to return results to tbe caller from the worker thread.
Return an error status to the main thread and raise the exception when that error status is seen.
Ig I could do it in a super hacky way by setting a flag, and then closing wss. When the close callback gets called, if that flag is set raise the error. Probably not going to work because that’s caught too, and may be in a thread (il need to look at my wss src again)
I may be able to do above but in the start function. where I have full control of everything.