Python 启动一个完全独立的流程
我想从python脚本Python 启动一个完全独立的流程,python,python-2.7,subprocess,fork,child-process,Python,Python 2.7,Subprocess,Fork,Child Process,我想从python脚本main.py启动一个进程。具体来说,我想运行以下命令: `nohup python ./myfile.py &` 并且文件myfile.py应该继续运行,即使在main.py脚本退出之后也是如此 我还希望获得新流程的pid 我试过: os.spawnl* os.exec* subprocess.Popen 当main.py脚本退出时,所有这些都将终止myfile.py 更新:我可以在xdg打开时使用os.startfile吗?这是正确的方法吗 示例 a
main.py
启动一个进程。具体来说,我想运行以下命令:
`nohup python ./myfile.py &`
并且文件myfile.py
应该继续运行,即使在main.py
脚本退出之后也是如此
我还希望获得新流程的pid
我试过:
os.spawnl*
os.exec*
subprocess.Popen
main.py
脚本退出时,所有这些都将终止myfile.py
更新:我可以在
xdg打开时使用os.startfile
吗?这是正确的方法吗
示例
a = subprocess.Popen([sys.executable, "nohup /usr/bin/python25 /long_process.py &"],\
stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)
print a.pid
如果我选中ps aux | grep long_进程
,则没有进程正在运行
long_process.py持续打印某些文本:不退出
我在这里做错了什么吗?您打开了长期运行的流程,并保留了一条通向它的管道。所以你希望和它谈谈。当你的启动程序脚本退出时,你就不能再和它说话了。长时间运行的进程收到一个
SIGPIPE
并退出
以下内容对我来说很有用(Linux、Python2.7)
创建长时间运行的可执行文件:
$ echo "sleep 100" > ~/tmp/sleeper.sh
运行Python REPL:
$ python
>>>
import subprocess
import os
p = subprocess.Popen(['/bin/sh', os.path.expanduser('~/tmp/sleeper.sh')])
# look ma, no pipes!
print p.pid
# prints 29893
退出REPL并查看进程仍在运行:
>>> ^D
$ ps ax | grep sleeper
29893 pts/0 S 0:00 /bin/sh .../tmp/sleeper.sh
29917 pts/0 S+ 0:00 grep --color=auto sleeper
如果要先与已启动的进程通信,然后让它继续运行,则有几个选项:
- 在长时间运行的进程中处理
,不要死在它上面。在启动程序进程退出后,不使用标准输入SIGPIPE
- 使用参数、环境或临时文件传递您想要的任何内容
- 在初始双向通信阶段完成后,使长时间运行的流程分叉
os.fork()
我看不到任何进程正在运行
您看不到任何进程正在运行,因为子python
进程立即退出。Popen
参数不正确
要启动完全独立的流程,您可以使用或使用systemd/supervisord/etc:
#!/usr/bin/python25
import daemon
from long_process import main
with daemon.DaemonContext():
main()
尽管在您的情况下,用正确的Popen
参数启动子项可能就足够了:
with open(os.devnull, 'r+b', 0) as DEVNULL:
p = Popen(['/usr/bin/python25', '/path/to/long_process.py'],
stdin=DEVNULL, stdout=DEVNULL, stderr=STDOUT, close_fds=True)
time.sleep(1) # give it a second to launch
if p.poll(): # the process already finished and it has nonzero exit code
sys.exit(p.returncode)
如果子进程不需要python2.5
,那么可以使用sys.executable
(使用与父进程相同的Python版本)
注意:代码在父进程中关闭
DEVNULL
,而不等待子进程完成(它对子进程没有影响)。您能给出一个失败的最小示例吗?在一个简单的python-c'导入子流程之后;subprocess.Popen([“sleep”,“60”])
ps的输出显示sleep
在Python退出后仍能正常运行。您使用一个参数运行Python,“nohup/usr/bin/python25…”
,它无法工作,因为python
可执行文件将在名为nohup/usr/bin/…的文件中查找脚本,该文件不存在。而且,由于在没有读取管道内容的情况下将stderr
指定为PIPE
,因此永远看不到错误消息。丢失nohup
和&
,只需运行subprocess.Popen([sys.executable,“/…/long_process.py]”)
。另外,除非你是认真的,否则不要将stdin
和stderr
指定为管道。nohup
在从shell启动进程时最有意义。在您的Popen
调用中,我看不到shell=True
。回答得很好,进程由于SIGPIPE
而终止是一个好问题。(在问题中的代码中,进程从未启动,但OP可能也尝试了其他因SIGPIPE
而启动和停止的变体)它没有创建“完全独立的进程”(这是python守护进程
包所做的)。也。虽然在简单的情况下,您的解决方案就足够了(您应该重定向到os.devnull
child的stdin/stdout/stderr,以避免等待输入和/或到终端的虚假输出)。@user4815162342:它不会因为Python 2中的SIGPIPE而消亡(问题有标签)。以下是重定向之所以重要的一个示例:它可能允许父进程在其子进程完成其输出写入之前退出:请注意,os.fork()
在这里使用nohup
是毫无意义的。它只做了两件事:(1)禁用HUP传播,这对于非交互shell已经关闭,因此不需要进一步禁用;(2)如果stdin、stdout和stderr连接到终端,则重定向它们(您可以自己做这件事;nohup.out 2>&1
,而您只做了nohup会做的完全相同的重定向)。就像@jfs的回答那样,完全不使用所有shell更有效。
with open(os.devnull, 'r+b', 0) as DEVNULL:
p = Popen(['/usr/bin/python25', '/path/to/long_process.py'],
stdin=DEVNULL, stdout=DEVNULL, stderr=STDOUT, close_fds=True)
time.sleep(1) # give it a second to launch
if p.poll(): # the process already finished and it has nonzero exit code
sys.exit(p.returncode)