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

时间:2013-07-30 02:14:27

标签: python subprocess

如何从Python脚本启动一个进程(例如另一个Python脚本),以便" child"过程完全脱离了父母",所以父母可以a)继续快乐的方式而不等待孩子完成,b)可以终止而不终止子过程?

父:

import os

print "Parent started"
os.system("./child.py")
print "Parent finished"

儿童:

import time

print "Child started"
time.sleep(10)
print "Child finished"

运行parent.py打印:

Parent started
Child started
Child finished
Parent finished

我想要它打印:

Parent started
Child started
Parent finished
(seconds later)
Child finished

3 个答案:

答案 0 :(得分:9)

由于您提到os.system,我认为值得一提的是您应该使用os.spawn*模式P_NOWAIT来实现“忘记”部分。

但是subprocess模块提供了os.systemos,spawn*等的替换,因此您应该使用它来代替

import subprocess
p = subprocess.Popen("./child.py")
print "pid = ", p.pid

请参阅Replacing os.spawn with subprocess.Popen

正如我在评论中所解释的,进程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"

答案 1 :(得分:1)

使用<a href="/">Back to login</a> 可以将简单的装饰器编写为asyncio

@background

生产

import asyncio
import time

def background(f):
    def wrapped(*args, **kwargs):
        return asyncio.get_event_loop().run_in_executor(None, f, *args, *kwargs)

    return wrapped

@background
def foo():
    time.sleep(1)
    print("foo() completed")

print("Hello")
foo()
print("I didn't wait for foo()")

答案 2 :(得分:0)

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

这里有一些代码:

<强> child.py

#!/usr/bin/python

import time
print "Child started"
time.sleep(10)
print "Child finished"

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"

<强>输出:

$ ./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
  • 注意如果父母被Ctrl-C中断
  • ,孩子将永远不会完成

parent.py ,使用os.system和&amp;

#!/usr/bin/python

import os
import time

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

time.sleep(5)

print "Parent finished"

<强>输出:

$ ./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

请注意孩子如何生活在Ctrl-C之外。