&引用;火与遗忘”;来自Python脚本的进程
如何从Python脚本启动一个进程(例如,另一个Python脚本),使“子”进程与“父”进程完全分离,这样父进程就可以a)在不等待子进程完成的情况下继续愉快地运行,b)在不终止子进程的情况下终止进程 家长:&引用;火与遗忘”;来自Python脚本的进程,python,subprocess,Python,Subprocess,如何从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
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, 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
$ ./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
子项:
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, 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
$ ./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
运行parent.py
打印:
Parent started
Child started
Child finished
Parent finished
我希望它打印的内容:
Parent started
Child started
Parent finished
(seconds later)
Child finished
既然您提到了
os.system
,我认为值得一提的是,您应该使用os.spawn*
和模式p_NOWAIT
来实现“忘记”部分
但是子流程
模块提供了对操作系统
、操作系统、spawn*
等的替换,所以您应该像这样使用它
import subprocess
p = subprocess.Popen("./child.py")
print "pid = ", p.pid
看
正如我在注释中所解释的,两个进程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"
回答我自己的问题:正如@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"
输出:
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, 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
$ ./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
输出:
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, 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
$ ./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
$./parent.py
父母开始
(孩子开始睡觉)
孩子开始
^CTraceback(最近一次通话最后一次):
文件“/parent.py”,第12行,在
时间。睡眠(5)
键盘中断
$Child已完成
注意孩子如何生活在Ctrl-C之外。使用
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
看看
subprocess
模块,特别是subprocess.Popen(…).pid
@sberry:Nice,看起来就像只使用subprocess.Popen(“./child.py”)
做的正是我需要的,尽管文档中根本不清楚。如果您添加您的评论作为答案,我很乐意接受,谢谢。根据平台的不同,您可能会在shell命令末尾添加一个&
,它也会起作用。@kevinsa5:yep,效果更好-我刚刚发现,使用Popen(),如果父进程被杀死,子进程似乎也会被杀死。嘿,谢谢你回答这个老问题。但是subprocess.Popen
有一个问题:如果父进程被终止,那么子进程也会被终止。你是什么意思?我试过这段代码,但至少在父母因自然原因死亡的情况下,孩子并没有被终止。Ctrl-C(所有信号)是不同的。终端接收信号并将其转发到前台进程组中的任何进程。此处的进程组包括parent.py和child.py,因此两者都会被杀死。我将尝试提供特定的Popen序列,以便在新进程组中创建子进程。