atexit not triggering after sys.exit() is called - python

I am trying to implement some basic close out tasks for an automation script I have written in python using pyautogui. I open a program and click certain buttons every day to create daily reports. But if something goes wrong, I need it to close the program it is using.
I tried using atexit.register, but it didn't seem to run when I trigger sys.exit(). So I wrote a test script to verify that it was triggering, and it isn't.
import atexit as a
import sys
def closeout():
print("atexit triggered, closing out")
print("starting program")
print("Registering closeout with atexit")
a.register(closeout)
print(r"triggering sys.exit()")
sys.exit()
it should print out the following:
"starting program"
"Registering closeout with atexit"
"triggering sys.exit()"
"atexit triggered, closing out"
but I don't get the last line.
Any thoughts? I'm running 3.7.2 if it matters.

When you "run module" from IDLE, it uses the compile builtin to build a code object from the associated file, and then runs it with exec. The process that runs the code doesn't exit, and SystemExit is caught and silently ignored in the IDLE interpreter - otherwise a script that included it would cause IDLE to quit! - so the atexit handler isn't run.
Furthermore, the default build of IDLE is configured to delete any register atexit functions when exiting, so your handler isn't run when IDLE itself eventually exits. (See the exit function in the cpython repo.)

Related

Is there a way to catch script manual termination?

I have a python script that launches a subprocess which then opens a python terminal window that displays its running logs/status output.
If the user closes the window, the process terminates - this is desirable. However, I cannot figure out a way to "catch" and log if the user manually terminates the script (closes window).
I have tried putting my main() in a try/except block but it seems that no exceptions are being raised (like a KeyboardInterrupt).
Also tried atexit package - but this seems only to take into effect at normal script termination.
Is there a way to log/print to file when a user terminates a script mid run?

Python how to check if the script has ended

So I am creating a script that needs to be run 24/7 on a server machine. I have created try/excepts to catch if the script stops for any reason and send me an email.
However, there is nothing that will happen if the command line is closed. Therefore, there will be no notification if the command line closes for any reason while the script stops.
I'm not sure how to add code to be able to do that, but it is important because I need to know anytime the script has been stopped. At the moment I can only check if it is stopped in any way except closing the window.
Here's a simple answer that I hope will work for you using python's atexit module:
import atexit
def exit_handler():
# do this stuff when the script exits
return
atexit.register(exit_handler)
Keep in mind the exit handler function won't execute if there is some sort of fatal internal error or it was terminated at a low level, but for this most part this should work :)

Wait and complete processes when Python script is stopped from PyCharm console?

Basically I am writing a script that can be stopped and resumed at any time. So if the user uses, say PyCharm console to execute the program, he can just click on the stop button whenever he wants.
Now, I need to save some variables and let an ongoing function finish before terminating. What functions do I use for this?
I have already tried atexit.register() to no avail.
Also, how do I make sure that an ongoing function is completed before the program can exit?
Solved it using a really bad workaround. I used all functions that are related to exit in Python, including SIG* functions, but uniquely, I did not find a way to catch the exit signal when Python program is being stopped by pressing the "Stop" button in PyCharm application. Finally got a workaround by using tkinter to open an empty window, with my program running in a background thread, and used that to close/stop program execution. Works wonderfully, and catches the SIG* signal as well as executing atexit . Anyways massive thanks to #scrineym as the link really gave a lot of useful information that did help me in development of the final version.
It looks like you might want to catch a signal.
When a program is told to stop a signal is sent to the process from the OS, you can then catch them and do cleanup before exit. There are many diffferent signals , for xample when you press CTRL+C a SIGINT signal is sent by the OS to stop your process, but there are many others.
See here : How do I capture SIGINT in Python?
and here for the signal library: https://docs.python.org/2/library/signal.html

Jenkins runs imported python script before main python script

I have a main build script which every jenkins job executes. This main script gets the job name(from Jenkins) and then executes the relevant script for that job name. Right now, I'm using subprocess.check_output to call the relevant script. I was thinking that instead of this, I should just import the script and then call the functions inside. I import it like this:
sys.path.insert(0,os.path.abspath(importLocation))
print("path", sys.path, os.path.abspath(importLocation))
import build
I also tried insert(-1,...) to put it at the end.The way I use it is that I have a couple of print statements in the main script before executing functions in this one.
print("Starting script...")
build.run()
This works fine on the console as it displays "Starting script" before running it. Unfortunately in Jenkins, it always shows build.run()'s output in the console before displaying anything from the main script. I even tried putting build.run() at the very bottom, in an if-statement etc.
Any ideas on how to make it run/show up in Jenkins in the right order?
The child process flushes its output buffers on exit but the prints from the parent are still in the parent's buffer. The solution is to flush the parent buffers before running the child:
print("Starting script...")
sys.stdout.flush()
build.run()

Python: Can't continually catch keyboardinterrupt in Windows?

In Python, I wrote the following code to see if I could get my program to not terminate upon Control+C like all those fancy terminal apps such as Vim or Dwarf Fortress.
def getinput():
x = input('enter something: ')
while True:
try:
getinput()
except KeyboardInterrupt:
pass
Unfortunately, in the Windows console, this script terminates after a few seconds. If I run it in IDLE, it works as expected. Python version is 3.2.1, 3.2 acted the same. Am I doing something wrong?
EDIT: If I hold down, Control+C, that is.
In order to not terminate on Control-C you need to set a signal handler.
From the Python doc here
Python installs a small number of
signal handlers by default: SIGPIPE is
ignored (so write errors on pipes and
sockets can be reported as ordinary
Python exceptions) and SIGINT is
translated into a KeyboardInterrupt
exception. All of these can be
overridden.
So you would need to install a signal handler to catch the SIGINT signal and do what you want on that.
The behavior with IDLE is probably that they have a handler installed that blocks the application exit.

Categories

Resources