python daemon thread is exiting when process is killed - python

I am starting a python script on one terminal and then from another terminal issuing a kill -9 to kill the process. I am hoping that even when the parent process is killed the thread will continue to execute and touch the file. But that is not happening. Any clue how I can achieve this?
import time,os
import threading
# Create your tests here.
def a(fname):
print "a"
time.sleep(20)
touch(fname)
def touch(fname, times=None):
with open(fname, 'a'):
os.utime(fname, times)
print "touched"
fname = "test.txt"
t = threading.Thread(target=a, args=(fname,))
t.setDaemon(True)
t.start()
t.join()

What you are trying is impossible, unfortunately. Threads can only run as long as their parent process runs. If you want to start executing some code from your script, but have that code continue executing after your script exits, you should move that code into a separate script and use the subprocess module to launch it. Specifically, you can use subprocess.Popen to launch the script without blocking to wait for it to complete:
subprocess.Popen(['./yourscript.py', '-a', 'opt'])

Related

Terminate Python Process and halt it's underlying os.system command line

I am running a script that launches a program via cmd and then, while the program is open, checks the log file of the program for errors. If any, close the program.
I cannot use taskkill command since I don't know the PID of the process and the image is the same as other processes that I don't want to kill.
Here is a code example:
import os, multiprocessing, time
def runprocess():
os.system('"notepad.exe"')
if __name__ == '__main__':
process = multiprocessing.Process(target=runprocess,args=[])
process.start()
time.sleep(5)
#Continuously checking if errors in log file here...
process_has_errors = True #We suppose an error has been found for our case.
if process_has_errors:
process.terminate()
The problem is that I want the notepad windows to close. It seems like the terminate() method will simply disconnect the process without closing all it's tasks.
What can I do to make sure to end all pending tasks in a process when terminating it, instead of simply disconnecting the process from those tasks?
You can use taskkill but you have to use the /T (and maybe /F) switch so all child processes of the cmd process are killed too. You get the process id of the cmd task via process.pid.
You could use a system call if you know the name of the process:
import os
...
if process_has_errors:
processName = "notepad.exe"
process.terminate()
os.system(f"TASKKILL /F /IM {processName}")

How to keep sub-process running after main process has exited?

I have a requirement to use python to start a totally independent process. That means even the main process exited, the sub-process can still run.
Just like the shell in Linux:
#./a.out &
then even if the ssh connection is lost, then a.out can still keep running.
I need a similar but unified way across Linux and Windows
I have tried the multiprocessing module
import multiprocessing
import time
def fun():
while True:
print("Hello")
time.sleep(3)
if __name__ == '__main__':
p = multiprocessing.Process(name="Fun", target=fun)
p.daemon = True
p.start()
time.sleep(6)
If I set the p.daemon = True, then the print("Hello") will stop in 6s, just after the main process exited.
But if I set the p.daemon = False, the main process won't exit on time, and if I CTRL+C to force quit the main process, the print("Hello") will also be stopped.
So, is there any way the keep print this "Hello" even the main process has exited?
The multiprocessing module is generally used to split a huge task into multiple sub tasks and run them in parallel to improve performance.
In this case, you would want to use the subprocess module.
You can put your fun function in a seperate file(sub.py):
import time
while True:
print("Hello")
time.sleep(3)
Then you can call it from the main file(main.py):
from subprocess import Popen
import time
if __name__ == '__main__':
Popen(["python", "./sub.py"])
time.sleep(6)
print('Parent Exiting')
The subprocess module can do it. If you have a .py file like this:
from subprocess import Popen
p = Popen([r'C:\Program Files\VideoLAN\VLC\vlc.exe'])
The file will end its run pretty quickly and exit, but vlc.exe will stay open.
In your case, because you want to use another function, you could in principle separate that into another .py file

Calling bash in thread

I need to call a bash Script Out of my Python Script.
import subprocess
subprocess.call("path/to/script.sh")
This is working, but the Script is starting another programm and therefore wont Exit. So my main Loop is blocked by the subprocess.
Is there a way to call the Script as Thread, not subprocess in Python?
You're better off using Popen
Execute a child program in a new process. On Unix, the class uses
os.execvp()-like behavior to execute the child program. On Windows,
the class uses the Windows CreateProcess() function. The arguments to
Popen are as follows
But if you insist on using threads this might also work:
import subprocess
import threading
def basher():
subprocess.call("echo hello > /tmp/test.txt", shell=True)
t = threading.Thread(target=basher)
t.start()
print('started')
# doing something else
t.join()
print('finished')
Don't use call; its only purpose is to block until the command exits. Use Popen directly:
import subprocess
p = subprocess.Popen("path/to/script.sh")
Now script.sh runs in the forked process while your Python script continues. Use p.wait() when you are ready to check if the script has completed.
Since you specifically asked for a separate thread, I recommend using the multiprocessing module (documentation):
from multiprocessing import Process
import subprocess
def myTask():
subprocess.call("path/to/script.sh")
p = Process(target=myTask) # creates a new thread which will run the function myTask
p.start() # starts the thread
# the script is now running in a separate thread
# you can now continue doing what you want
If at some point in your python script (e.g. before exiting) you want to make sure that the bash script has finished running you can call p.join() which blocks the python script until the bash script has terminated.

How to kill subprocess python in windows

How would I go about killing a process on Windows?
I am starting the process with
self.p = Process(target=self.GameInitialize, args=(testProcess,))
self.p.start()
I have tried
self.p.kill()
self.p.terminate()
os.kill(self.p.pid, -1)
os.killpg(self.p.pid, signal.SIGTERM) # Send the signal to all the process groups
Errors
Process Object has no Attribute kill
Process Object has no Attribute terminate
Access Denied
I cannot use .join.
On windows, os.killpg will not work because it sends a signal to the process ID to terminate. This is now how you kill a process on Windows, instead you have to use the win32 API's TerminateProcess to kill a process.
So, you can kill a process by the following on windows:
import signal
os.kill(self.p.pid, signal.CTRL_C_EVENT)
If the above does not work, then try signal.CTRL_BREAK_EVENT instead.
I had to do it using this method from this link:
subprocess.call(['taskkill', '/F', '/T', '/PID', str(self._active_process.pid)])
This is because self._active_process.kill() was not adequate
You should provide a minimal, working example of the problem you are having. As show below, this minimal, working example correctly terminates the process (Tested on Python 2.7.5 64-bit), so the error you are seeing lies in code you haven't shown.
import multiprocessing as mp
import time
def work():
while True:
print('work process')
time.sleep(.5)
if __name__ == '__main__':
p = mp.Process(target=work)
p.start()
for i in range(3):
print('main process')
time.sleep(1)
p.terminate()
for i in range(3):
print('main process')
time.sleep(.5)
Output:
main process
work process
work process
main process
work process
work process
main process
work process
work process
main process
main process
main process
os.kill(self.p.pid, -9)
Works. I am unsure why -1 returns a access denied error but -9 does not.

When I use os.system() to open a .py file in Python it automatically closes it immediately. How do I fix this?

I'm writing a script that needs to open another script, but continue running the main script such that both scripts are running simultaneously.
I've tried execfile() but the file doesn't open. When I use os.system(somefile.py) it successfully opens the .py file via console but immediately closes it. Are there alternatives so that I can run a python script within a main python script, but have both processes running simultaneously without conflicting one another?
Here is sample code I've tested:
import os
file_path = 'C:\\Users\\Tyler\\Documents\\Multitask Bot\\somefile.py'
def main():
os.system(file_path)
if __name__ == '__main__':
main()
execfile() and os.system() will block the parent process until the child exits. Use subprocess.Popen(), e.g.
import subprocess, time
file_path = 'C:\\Users\\Tyler\\Documents\\Multitask Bot\\somefile.py'
def main():
child = subprocess.Popen(['python', file_path])
while child.poll() is None:
print "parent: child (pid = %d) is still running" % child.pid
# do parent stuff
time.sleep(1)
print "parent: child has terminated, returncode = %d" % child.returncode
if __name__ == '__main__':
main()
This is just one way to handle it. You may want to collect stdout and/or stderr from the child and possibly send data to the child's stdin. Read up on the subprocess module.
If you want to run another script simultaneously, consider the subprocess module.
Your problem can be that that file is not executed in C:\\Users\\Tyler\\Documents\\Multitask Bot\\
but somewhere else. The local import may fail.
could you try executing os.chdir('C:\\Users\\Tyler\\Documents\\Multitask Bot\\') before os.system ?

Categories