15

如何从 Python 脚本启动一个进程(例如另一个 Python 脚本),以便“子”进程与“父”完全分离,因此父进程可以 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
4

3 回答 3

11

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

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

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

请参阅用 subprocess.Popen 替换 os.spawn

正如我在评论中解释的那样,两个进程parent.py仍然child.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"
于 2014-06-10T06:31:07.100 回答
3

使用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()")

生产

>>> Hello
>>> I didn't wait for foo()
>>> foo() completed
于 2018-11-12T04:27:39.617 回答
1

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

这是一些代码:

孩子.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 和 &

#!/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 之外是如何生活的。

于 2014-06-10T20:17:56.050 回答