Reputation: 59323
I'm working on a nifty little function:
def startProcess(name, path):
"""
Starts a process in the background and writes a PID file
returns integer: pid
"""
# Check if the process is already running
status, pid = processStatus(name)
if status == RUNNING:
raise AlreadyStartedError(pid)
# Start process
process = subprocess.Popen(path + ' > /dev/null 2> /dev/null &', shell=True)
# Write PID file
pidfilename = os.path.join(PIDPATH, name + '.pid')
pidfile = open(pidfilename, 'w')
pidfile.write(str(process.pid))
pidfile.close()
return process.pid
The problem is that process.pid
isn't the correct PID. It seems it's always 1 lower than the correct PID. For instance, it says the process started at 31729, but ps
says it's running at 31730. Every time I've tried it's off by 1. I'm guessing the PID it returns is the PID of the current process, not the started one, and the new process gets the 'next' pid which is 1 higher. If this is the case, I can't just rely on returning process.pid + 1
since I have no guarantee that it'll always be correct.
Why doesn't process.pid
return the PID of the new process, and how can I achieve the behaviour I'm after?
Upvotes: 63
Views: 138852
Reputation: 1798
From the documentation at http://docs.python.org/library/subprocess.html:
Popen.pid The process ID of the child process.
Note that if you set the shell argument to True, this is the process ID of the spawned shell.
If shell
is false, it should behave as you expect, I think.
If you were relying on shell
being True
for resolving executable paths using the PATH
environment variable, you can accomplish the same thing using shutil.which
instead, then pass the absolute path to Popen instead. (As an aside, if you are using Python 3.5 or newer, you should be using subprocess.run
rather than Popen.
Upvotes: 57