I am working currently on Raspbian. My Problem is i have a Python scrip with a infinite Loop that never should stop. In This script i want to call another script without the main script stopping. I tried different methodes to do this like:
import test1
test1.some_func()
or
execfile("test1.py")
or
import subprocess
subprocess.call("python test1.py")
I could start the test1.py script with these solutions, but the script that called it would stop working. So my question is how to start a second script without the first one to stop.
subprocess.call waits for the command to complete and thus blocks your loop. You should use something like process = subprocess.Popen(["python", "test1.py"]). If you want to wait for the process to terminate, you can then call process.wait().
Related
I have a program that produces a csv file and right at the end I am using os.startfile(fileName) but then due to the program finishing execution the opening file just closes also, same happens if I add a sleep after also, file loads up then once the sleep ends it closes again?
Any help would be appreciated.
From the documentation for os.startfile:
startfile() returns as soon as the associated application is launched. There is no option to wait for the application to close, and no way to retrieve the application’s exit status.
When using this function, there is no way to make your script wait for the program to complete because you have no way of knowing when it is complete. Because the program is being launched as a subprocess of your python script, the program will exit when the python script exits.
Since you don't say in your question exactly what the desired behavior is, I'm going to guess that you want the python script to block until the program finishes execution (as opposed to detaching the subprocess). There are multiple ways to do this.
Use the subprocess module
The subprocess module allows you to make a subprocess call that will not return until the subprocess completes. The exact call you make to launch the subprocess depends heavily on your specific situation, but this is a starting point:
subprocess.Popen(['start', fileName], shell=True)
Use input to allow user to close script
You can have your script block until the user tells the python script that the external program has closed. This probably requires the least modification to your code, but I don't think it's a good solution, as it depends on user input.
os.startfile(fileName)
input('Press enter when external program has completed...')
is there a way to restart another script in another shell?
i have script that sometimes stuck waiting to read email from gmail and imap. from another script i would like to restart the main one but without stopping the execution of the second
i have tried:
os.system("C:\Users\light\Documents\Python\BOTBOL\Gmail\V1\send.py")
process = subprocess.Popen(["python", "C:\Users\light\Documents\Python\BOTBOL\Gmail\V1\send.py"])
but both run the main in the second's shell
EDIT:
sorry, for shell i mean terminal window
After your last comment and as the syntax show that you are using Windows, I assume that you want to launch a Python script in another console. The magic word here is START if you want that the launching execute in parallel with the new one, or START /W if you want to wait for the end of the subprocess.
In your case, you could use:
subprocess.call(["cmd.exe", "/c", "START", "C:\Path\To\PYTHON.EXE",
"C:\Users\light\Documents\Python\BOTBOL\Gmail\V1\send.py"])
Subprocess has an option called shell which is what you want. Os calls are blocking which means that only after the command is completed will the interpreter move to the next line. On the other hand subprocess popens are non blocking, however both these commands will spawn off child process from the process running this code. If you want to run in shell and get access shell features to execute this , try the shell = True in subprocess.
I could try and explain everything you need but I think this video will do it better: Youtube Video about multithreading
This will allow you to run 2 things f.e.
Have 1 run on checkin email and the other one on inputs so it wont stop at those moments and making multiple 'shelves' possible, as they are parallel.
If you really want to have a different window for this, i am sorry and I can not help.
Hope this was were you were looking for.
thanks for helping!
I want to start and stop a Python script from a shell script. The start works fine, but I want to stop / terminate the Python script after 10 seconds. (it's a counter that keeps counting). bud is won't stop.... I think it is hanging on the first line.
What is the right way to start wait for 10 seconds en stop?
Shell script:
python /home/pi/count1.py
sleep 10
kill /home/pi/count1.py
It's not working yet. I get the point of doing the script on the background. That's working!. But I get another comment form my raspberry after doing:
python /home/pi/count1.py &
sleep 10; kill /home/pi/count1.py
/home/pi/sebastiaan.sh: line 19: kill: /home/pi/count1.py: arguments must be process or job IDs
It's got to be in the: (but what? Thanks for helping out!)
sleep 10; kill /home/pi/count1.py
You're right, the shell script "hangs" on the first line until the python script finishes. If it doesn't, the shell script won't continue. Therefore you have to use & at the end of the shell command to run it in the background. This way, the python script starts and the shell script continues.
The kill command doesn't take a path, it takes a process id. After all, you might run the same program several times, and then try to kill the first, or last one.
The bash shell supports the $! variable, which is the pid of the last background process.
Your current example script is wrong, because it doesn't run the python job and the sleep job in parallel. Without adornment, the script will wait for the python job to finish, then sleep 10 seconds, then kill.
What you probably want is something like:
python myscript.py & # <-- Note '&' to run in background
LASTPID=$! # Save $! in case you do other background-y stuff
sleep 10; kill $LASTPID # Sleep then kill to set timeout.
You can terminate any process from any other if OS let you do it. I.e. if it isn't some critical process belonging to the OS itself.
The command kill uses PID to kill the process, not the process's name or command.
Use pkill for that.
You can also, send it a different signal instead of SIGTERM (request to terminate a program) that you may wish to detect inside your Python application and respond to it.
For instance you may wish to check if the process is alive and get some data from it.
To do this, choose one of the users custom signals and register them within your Python program using signal module.
To see why your script hangs, see Austin's answer.
I have a python script named "prog.py". I want to add a feature that opens a new process that watches the operation of the current script. When the script terminates, the process recognizes the termination and then invokes a certain function. Here is a pseudo-code:
while (script is active):
sleep(1) # check its status once a second
func()
Do you have any idea how to do it?
Is there a reason the other process needs to be launched first? Seems like you could do this more efficiently and reliably by just execing when the first process completes. For example:
import atexit
import os
atexit.register(os.execlp, 'afterexitscript.py', 'afterexitscript.py', 'arg1', 'arg2')
When the current Python process exits, it will seamlessly replace itself with your other script, which need not go to the trouble of including a polling loop. Or you could just use atexit to execute whatever func is directly in your main script and avoid a new Python launch.
I'm trying to call a windows-cmd-file by python's subprocess.Popen module. This script then calls a powershell file that contains the problem logic. The call works fine and the script is executed, anyway it does not seem to terminate.
My current code is the following:
pRun = subprocess.Popen([r'C:\runps.cmd', 'C:\psfile.ps1', 'arg2'], shell=False)
pRun.wait()
... rest of code
So far I am not interested in interaction with the script (like stdin or stdout), I just want to call the script and know when it is terminated.
When I call the same command (C:\runpw.cmd C:\psfile.ps1 arg2) from the windows command line it works fine, doing all the desired actions and then terminates s.t. I can input the next command. That's why I assume that python might wait forever for the termination of a process or thread, that just won't terminate.
Thanks for your help in advance!
post edit:
The code will be executed on a windows machine