"消防并忘记"来自Python脚本的过程

Ser*_*gey 7 python subprocess

如何从Python脚本启动一个进程(例如另一个Python脚本),以便"子"进程与"父"完全分离,因此父进程可以a)继续其快乐方式而无需等待子进程完成和b)可以在不终止子进程的情况下终止?

家长:

import os

print "Parent started"
os.system("./child.py")
print "Parent finished"
Run Code Online (Sandbox Code Playgroud)

儿童:

import time

print "Child started"
time.sleep(10)
print "Child finished"
Run Code Online (Sandbox Code Playgroud)

运行parent.py打印:

Parent started
Child started
Child finished
Parent finished
Run Code Online (Sandbox Code Playgroud)

我想要它打印:

Parent started
Child started
Parent finished
(seconds later)
Child finished
Run Code Online (Sandbox Code Playgroud)

ece*_*ulm 9

既然你提到过os.system,我认为值得一提的是你应该os.spawn*用模式P_NOWAIT来实现"忘记"部分.

但是subprocess模块提供了等等的替换os.system,os,spawn*所以你应该这样使用它

import subprocess
p = subprocess.Popen("./child.py")
print "pid = ", p.pid
Run Code Online (Sandbox Code Playgroud)

请参见使用subprocess.Popen替换os.spawn

正如我在评论这两个过程解释parent.pychild.py仍然在同一进程群,因此,终端将信号转发(喜欢Ctrl-C)所有进程前台进程组中,以便两者都将被杀死你的时候Ctrl-C.因此,如果您不希望这样,您可以强制child.py进入具有以下内容的新流程组:

#!/usr/bin/env python
import subprocess
import time
import os
p = subprocess.Popen("./child.py", preexec_fn=os.setsid)
print "pid = ", p.pid
time.sleep(30) # Ctrl-C at this point will not kill child.py
print "parent exit"
Run Code Online (Sandbox Code Playgroud)


Ser*_*gey 1

回答我自己的问题:我最终只是按照 @kevinsa 的建议在命令末尾使用os.systemwith 。这允许在不终止子进程的情况下终止父进程。&

这是一些代码:

孩子.py

#!/usr/bin/python

import time
print "Child started"
time.sleep(10)
print "Child finished"
Run Code Online (Sandbox Code Playgroud)

Parent.py,使用 subprocess.Popen:

#!/usr/bin/python

import subprocess
import time

print "Parent started"
subprocess.Popen("./child.py")
print "(child started, sleeping)"

time.sleep(5)

print "Parent finished"
Run Code Online (Sandbox Code Playgroud)

输出:

$ ./parent.py
Parent started
(child started, sleeping)
Child started
^CTraceback (most recent call last):
Traceback (most recent call last):
  File "./child.py", line 5, in <module>
  File "./parent.py", line 13, in <module>
        time.sleep(10)
time.sleep(5)
KeyboardInterrupt
KeyboardInterrupt
Run Code Online (Sandbox Code Playgroud)
  • 请注意,如果父级被 Ctrl-C 打断,子级将永远无法完成

Parent.py,使用 os.system 和 &

#!/usr/bin/python

import os
import time

print "Parent started"
os.system("./child.py &")
print "(child started, sleeping)"

time.sleep(5)

print "Parent finished"
Run Code Online (Sandbox Code Playgroud)

输出:

$ ./parent.py
Parent started
(child started, sleeping)
Child started
^CTraceback (most recent call last):
  File "./parent.py", line 12, in <module>
    time.sleep(5)
KeyboardInterrupt

$ Child finished
Run Code Online (Sandbox Code Playgroud)

注意孩子在 Ctrl-C 之外的生活。