Reputation: 101
i would like my Python script to check, if it is already running and if yes, kill the old process. i tried this, but it doesn't really work...
import os
import subprocess
import signal
process_name = "python " + os.path.abspath(__file__)
proc = subprocess.Popen(["pgrep", process_name], stdout=subprocess.PIPE)
# Kill process.
for pid in proc.stdout:
os.kill(int(pid), signal.SIGTERM)
# Check if the process that we killed is alive.
try:
os.kill(int(pid), 0)
raise Exception("""wasn't able to kill the process
HINT:use signal.SIGKILL or signal.SIGABORT""")
except OSError as ex:
continue
It doesn't kill the old process and runs multiple times now.
Upvotes: 10
Views: 36070
Reputation: 1119
If you want a cross-platform solution without using a library, you can use a PID file, which is simply a TXT file with your process identifier (PID) inside.
from os import getpid
from os.path import exists
from psutil import pid_exists, Process
PATH_PIDFILE = 'pid.txt'
def already_running():
my_pid = getpid()
if exists(PATH_PIDFILE):
with open(PATH_PIDFILE) as f:
pid = f.read()
pid = int(pid) if pid.isnumeric() else None
if pid is not None and pid_exists(pid) and Process(pid).cmdline() == Process(my_pid).cmdline():
return True
with open(PATH_PIDFILE, 'w') as f:
f.write(str(my_pid))
return False
Upvotes: 4
Reputation: 357
This question is very similar to Check to see if python script is running
I suggest you use the PidFile module, it will handle everything for you.
import pidfile
import time
print('Starting process')
try:
with pidfile.PIDFile():
print('Process started')
time.sleep(30)
except pidfile.AlreadyRunningError:
print('Already running.')
print('Exiting')
Try to run twice this script with two terminals
I am not related to the owner of the library, I just found it
Upvotes: 3
Reputation: 91
My current solution looks like this (on OSX). I am using pgrep in combination with regexp
import subprocess
cmd = ['pgrep -f .*python.*testing03.py']
process = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
my_pid, err = process.communicate()
if len(my_pid.splitlines()) >0:
print("Running")
exit()
else:
print("Not Running")
As far as i have tested this should work even if the python string differs. Location of the script doesn't matter either
Upvotes: 9
Reputation: 1200
Starting from Dan's answer I came up with
> ps -f -C python | grep 'sleep.py'
userid 21107 2069 0 12:51 pts/3 00:00:00 anypath/python anypath/sleep.py
This still has a lot of the problems described in the previous answers, however, it at least gets rid of seeing grep in the result and being dependent on the path of the script.
It is also possible to check for several python versions with:
> ps -f -C python,python2.7 | grep 'sleepy.py'
EDIT: This is not working correctly if multiple python3 instances are running. Better use:
> pgrep -a python | grep 'sleepy.py'
Upvotes: 4
Reputation: 39824
Determining if a python script is running using your pgrep
based method is not reliable. For example:
> ps -ef | grep 'python sleep.py'
userid 21107 2069 0 12:51 pts/3 00:00:00 python sleep.py
userid 21292 2069 0 13:08 pts/3 00:00:00 grep python sleep.py
> pgrep 'python sleep.py'
>
Additional difficulties in identifying a running python script by its name:
python
string may differ, depending on how the script is executed, for example it may look like this:/usr/bin/python2.7 sleep.py
os.path.abspath(__file__)
method to locate the script in the process name may fail if the script is a symlink to the actual file and can be executed from both locationsExample:
> cat abs_path.py
import os
print os.path.abspath(__file__)
> ls -l abs_path.py
lrwxrwxrwx 1 userid at 15 Apr 22 13:22 abs_path.py -> bin/abs_path.py
> python abs_path.py
/home/userid/abs_path.py
> python bin/abs_path.py
/home/userid/bin/abs_path.py
My personal preference in approaching such problem is to have the script create a pidfile in a unique, well known location in which it'll place its own pid. This makes determining the pid of a potentially already running process much more reliable.
You'll still have to take into account the race condition in creating the pidfile and reliably writing into it self's pid. Typically re-checking the file content and committing suicide if mismatches are detected is sufficient to ensure at most a single running process instance exists, regardless of how the process is actually named.
Upvotes: 5