I'm doing a small project related to data engineering. I have 2 processes. First is responsible for sorting, analysing and making graphs. The second is only the loading bar, simple gui which is shown to user why data operators are done. The loading bar stops when the information from multiprocessing Event is send. But I want to stop whole function from second process when user close the window. Basically I want to stop python script when the window is closed. I tried with options:
sys.exit(0), exit(0), quit() and os._exit(0) but every option kills only the process instead of running whole script. I want to do similar option to ctrl+c in vsc terminal. Did I missed sth or it doesn't work in general?
Related
I am fairly new to programming with Python, so forgive me if this is trivial.
I know that when programming microcontrollers it is possible to interrupt the main program (e.g. on button press or due to a timer). The interrupt leads to a code outside of the main program that is then executed. Afterwards, the main program is continued to be executed. Hereby, the interrupt handler remembers where it interrupted the main program and returns to that exact point within the code. Is it possible to implement that on Python as well?
I looked into the "threading"-library but it doesn't seem fit, since I don't want several tasks running parallel. There it seems like I have to check for an event on every second line of my main code to ensure that it really interrupts the program immediately.
If you need some context:
I am implementing a program using the "PsychoPy Coder" (PsychoPy v2021.2.3) on Windows 10.
I expect the program (when finished) to run for at least an hour, depending on the user. I want this program to be interrupted every 60 to 90 seconds for a "baseline task" the user has to solve. This baseline task will last for about 6 to 9 seconds and the actual program should continue afterwards. Also, I want the user to be able to abort the program with a specific button at anytime.
I would be very thankful for any hint on an elegant way of programming this :) Have a nice day!
I have a huge problem. I am working in a Web Python Project, where, after click in a button, a specific controller is called and then another function, present in a python module, is called as well, as shown in my code below. However , I need a second button that stops the process of the stream function controller.
import analyser
def stream():
analyser.get_texts()
response.flash = "Analysis Done."
return ""
I've been searching a lot how to stop a process by an external event (something similar to interruption), but the solutions that I've got, all of them, were about how to stop python script using sys.exit() ou programatically by a return statement, for example. None of these solutions actually work for me.
I want that the user be able to stop that function whenever he wants, once that my function analyser.get_texts() remains processing all the time.
So, my question is how can I stop the execution of stream function, through a button click on my view? Thanks.
If I understand you correctly, then your analyser doesn't provide its own way to terminate an ongoing calculation. You will therefore need to wrap it into something that allows you to terminate the analyser without its "consent".
The right approach for that depends on how bad terminating the analyser in that way is: does it leave resources in a bad state?
Depending on that, you have multiple options:
Run your analysis in a separate process. These can be cleanly killed from the outside. Note that it's usually not a good idea to forcefully stop a thread, so use processes instead.
Use some kind of asynchronous task management that lets you create and stop tasks (e.g. Celery).
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
I created a GUI with PyQt which implements the buttons "Start" and "Stop".
When I click on "Start" a huge python Script is started. The function of "Stop" has to end this python script, but when I start the script it runs and I can't stop it. I even can't activate anything else on the GUI and I get no reaction from it. So i have to wait the long time until the python script ends.
How can I implement the methods so that I can interrupt the script with the "Stop" button even when I want?
Since you do everything in the QButton.clicked signal, your GUI locks up until you exit that function.
My solution i used in a small project was to seperate it into a GUI and worker process.
Use multiprocessing.Process to do your processing and have it send the results over a multiprocessing.Pipe.
The worker also has a second Pipe to recieve commands (my project just uses one command - exit)
In the GUI, you create 2 Pipes: one for results, one for commands.
Initialize the worker with both pipes and start the process.
The next step would be to have a QTimer poll the pipe for results and display them.
By doing so, your UI stays responsive while the calculations happen in the background.
I'm wondering how to call an external program in such a way that allows the user to continue to interact with my program's UI (built using tkinter, if it matters) while the Python program is running. The program waits for the user to select files to copy, so they should still be able to select and copy files while the external program is running. The external program is Adobe Flash Player.
Perhaps some of the difficulty is due to the fact that I have a threaded "worker" class? It updates the progress bar while it does the copying. I would like the progress bars to update even if the Flash Player is open.
I tried the subprocess module. The program runs, however it prevents the user from using the UI until the Flash Player is closed. Also, the copying still seems to occur in the background, it's just that the progress bar does not update until the Flash Player is closed.
def run_clip():
flash_filepath = "C:\\path\\to\\file.exe"
# halts UI until flash player is closed...
subprocess.call([flash_filepath])
Next, I tried using the concurrent.futures module (I was using Python 3 anyway). Since I'm still using subprocess to call the application, it's not surprising that this code behaves exactly like the above example.
def run_clip():
with futures.ProcessPoolExecutor() as executor:
flash_filepath = "C:\\path\\to\\file.exe"
executor.submit(subprocess.call(animate_filepath))
Does the problem lie in using subprocess? If so, is there a better way to call the external program? Thanks in advance.
You just need to keep reading about the subprocess module, specifically about Popen.
To run a background process concurrently, you need to use subprocess.Popen:
import subprocess
child = subprocess.Popen([flash_filepath])
# At this point, the child process runs concurrently with the current process
# Do other stuff
# And later on, when you need the subprocess to finish or whatever
result = child.wait()
You can also interact with the subprocess' input and output streams via members of the Popen-object (in this case child).