Opening a process with Popen and getting the PID

Question:

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?

Asked By: Hubro

||

Answers:

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.

Answered By: krousey
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.