【问题标题】:python - subprocess.Popen().pid return the pid of the parent scriptpython - subprocess.Popen().pid 返回父脚本的pid
【发布时间】:2015-06-25 01:57:51
【问题描述】:

我正在尝试从另一个 Python 脚本运行一个 Python 脚本,并获取它的 pid 以便稍后我可以杀死它。

我尝试了subprocess.Popen() 与父脚本的参数shell=True', but thepidattribute returns thepid`,所以当我尝试杀死子进程时,它会杀死父进程。

这是我的代码:

proc = subprocess.Popen(" python ./script.py", shell=True)
pid_ = proc.pid
.
.
.
# later in my code

os.system('kill -9 %s'%pid_)

#IT KILLS THE PARENT :(

【问题讨论】:

    标签: python subprocess


    【解决方案1】:

    shell=True 启动一个新的 shell 进程。 proc.pid 是那个 shell 进程的 pid。 kill -9 杀死 shell 进程,使孙子 python 进程成为孤儿。

    如果孙 python 脚本可以产生自己的子进程并且您想杀死整个进程树,请参阅How to terminate a python subprocess launched with shell=True

    #!/usr/bin/env python
    import os
    import signal
    import subprocess
    
    proc = subprocess.Popen("python script.py", shell=True, preexec_fn=os.setsid) 
    # ...
    os.killpg(proc.pid, signal.SIGTERM)
    

    如果script.py 没有产生任何进程,则使用@icktoofay suggestion:删除shell=True,使用列表参数,然后调用proc.terminate()proc.kill()——后者最终总是有效:

    #!/usr/bin/env python
    import subprocess
    
    proc = subprocess.Popen(["python", "script.py"]) 
    # ...
    proc.terminate()
    

    如果你想从不同的目录运行你的父脚本;你可能需要get_script_dir() function

    考虑导入 python 模块并运行它的函数,使用它的对象(可能通过multiprocessing)而不是作为脚本运行它。这是code example that demonstrates get_script_dir() and multiprocessing usage

    【讨论】:

    • 应该是os.killpg(os.getpgid(proc.pid), signal.SIGTERM) 而不是os.killpg(proc.pid, signal.SIGTERM)
    • @PJ_Finnegan:它按原样工作。 os.getpgid(proc.pid) == proc.pid 在这里。
    • +jfs true,但是在引用的示例和我测试过的一些代码中,它也可以在 Popen 中不使用 setsid() 和使用 killpg 的情况下工作。我认为Popen 会自动为顶层shell 分配一个新的组ID。另外,preexec_fn 不是线程安全的。检查这个:stackoverflow.com/q/42257512/1141215
    • @PJ_Finnegan: 1- 如果你删除了 setsid();代码中断 2- Python 2 中没有start_new_session。查看shebang(它是python,而不是python3) 3- 经验法则:除非代码明确称为“线程安全”;它不是。除非您看到相反的明确声明,否则您不应假设任何代码都是线程安全的。
    【解决方案2】:

    所以不用shell直接运行:

    proc = subprocess.Popen(['python', './script.py'])
    

    顺便说一句,您可能需要考虑将硬编码的'python' 更改为sys.executable。此外,您可以使用 proc.kill() 来终止进程,而不是提取 PID 并使用它;此外,即使您确实需要通过 PID 终止,您也可以使用 os.kill 终止进程而不是生成另一个命令。

    【讨论】:

    • @farhawa:您能否更新您的问题以澄清发生了什么?我理解你的意思是有一个 Python 解释器产生一个 shell 产生另一个 Python 解释器,而 kill 杀死 shell 而不是所需的从属解释器。
    猜你喜欢
    • 2014-11-12
    • 2013-03-15
    • 2021-07-16
    • 2014-08-14
    • 2018-07-02
    • 1970-01-01
    • 2020-12-12
    • 2015-02-09
    • 1970-01-01
    相关资源
    最近更新 更多