使用 Popen 打开进程并获取 PID

2022-01-18 00:00:00 python subprocess popen

问题描述

我正在开发一个漂亮的小功能:

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

问题在于 process.pid 不是正确的 PID.它似乎总是比正确的PID低1.例如,它说进程从 31729 开始,但 ps 说它在 31730 运行.每次我尝试它都会关闭 1.我猜它返回的 PID 是当前 进程,而不是启动的进程,并且新进程获得高 1 的下一个"pid.如果是这种情况,我不能仅仅依靠返回 process.pid + 1 因为我不能保证它总是正确的.

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.

process.pid为什么不返回新进程的PID,如何实现我想要的行为?

Why doesn't process.pid return the PID of the new process, and how can I achieve the behaviour I'm after?


解决方案

来自 http://docs.python.org/library/subprocess.html:

Popen.pid 子进程的进程ID.

Popen.pid The process ID of the child process.

注意,如果你将shell参数设置为True,这就是进程生成的 shell 的 ID.

Note that if you set the shell argument to True, this is the process ID of the spawned shell.

如果 shell 为假,我认为它的行为应该如您所愿.

If shell is false, it should behave as you expect, I think.

如果您依赖 shellTrue 来使用 PATH 环境变量解析可执行路径,则可以使用 shutil.which 代替,然后通过而是 Popen 的绝对路径.(顺便说一句,如果您使用的是 Python 3.5 或更高版本,则应该使用 subprocess.run 而不是 Popen.

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.

相关文章