Python 启动一个完全独立的进程
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/27624850/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Launch a completely independent process
提问by Garfield
I want to initiate a process from my python script main.py
. Specifically, I want to run the below command:
我想从我的 python 脚本启动一个进程main.py
。具体来说,我想运行以下命令:
`nohup python ./myfile.py &`
and the file myfile.py
should continue running, even after the main.py
script exits.
并且该文件myfile.py
应该继续运行,即使在main.py
脚本退出之后也是如此。
I also wish to get the pid
of the new process.
我也希望得到pid
新进程的。
I tried:
我试过:
os.spawnl*
os.exec*
subprocess.Popen
os.spawnl*
os.exec*
subprocess.Popen
and all are terminating the myfile.py
when the main.py
script exits.
并且所有都myfile.py
在main.py
脚本退出时终止。
Update:Can I use os.startfile
with xdg-open
? Is it the right approach?
更新:我可以用os.startfile
用xdg-open
?这是正确的方法吗?
Example
例子
a = subprocess.Popen([sys.executable, "nohup /usr/bin/python25 /long_process.py &"],\
stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)
print a.pid
If I check ps aux | grep long_process
, there is no process running.
如果我检查ps aux | grep long_process
,则没有进程正在运行。
long_process.pywhich keeps on printing some text: no exit.
long_process.py继续打印一些文本:没有退出。
Am I doing anything wrong here?
我在这里做错了什么吗?
采纳答案by 9000
You open your long-running process and keep a pipe to it. So you expect to talk to it. When yor launcher script exits, you can no longer talk to it. The long-running process receives a SIGPIPE
and exits.
您打开长期运行的进程并保留一个管道。所以你希望与它交谈。当您的启动器脚本退出时,您将无法再与它交谈。长时间运行的进程收到 aSIGPIPE
并退出。
The following just worked for me (Linux, Python 2.7).
以下仅对我有用(Linux,Python 2.7)。
Create a long-running executable:
创建一个长时间运行的可执行文件:
$ echo "sleep 100" > ~/tmp/sleeper.sh
Run Python REPL:
运行 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
Exit the REPL and see the process still running:
退出 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
If you want to first communicate to the started process and then leave it alone to run further, you have a few options:
如果您想首先与启动的进程通信,然后让它继续运行,您有几个选择:
- Handle
SIGPIPE
in your long-running process, do not die on it. Live without stdin after the launcher process exits. - Pass whatever you wanted using arguments, environment, or a temporary file.
- If you want bidirectional communication, consider using a named pipe (man mkfifo) or a socket, or writing a proper server.
- Make the long-running process fork after the initial bi-direcional communication phase is done.
- 手柄
SIGPIPE
在长期运行过程中,不就可以死了。启动器进程退出后,无需标准输入即可存活。 - 使用参数、环境或临时文件传递您想要的任何内容。
- 如果您想要双向通信,请考虑使用命名管道 ( man mkfifo) 或套接字,或者编写适当的服务器。
- 在初始双向通信阶段完成后,使长时间运行的进程分叉。
回答by Hannes Karppila
You can use os.fork()
.
您可以使用os.fork()
.
import os
pid=os.fork()
if pid==0: # new process
os.system("nohup python ./myfile.py &")
exit()
# parent process continues
回答by jfs
I could not see any process running.
我看不到任何进程正在运行。
You don't see any process running because the child python
process exits immediately. The Popen
arguments are incorrect as user4815162342 says in the comment.
您看不到任何进程正在运行,因为子python
进程立即退出。该Popen
参数是不正确的,user4815162342在注释中说。
To launch a completely independentprocess, you could use python-daemon
packageor use systemd/supervisord/etc:
要启动一个完全独立的进程,您可以使用python-daemon
package或使用 systemd/supervisord/etc:
#!/usr/bin/python25
import daemon
from long_process import main
with daemon.DaemonContext():
main()
Though it might be enough in your case, to start the child with correct Popen
arguments:
尽管在您的情况下可能就足够了,但要以正确的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)
If the child process doesn't require python2.5
then you could use sys.executable
instead (to use the same Python version as the parent).
如果子进程不需要,python2.5
那么您可以sys.executable
改用(使用与父进程相同的 Python 版本)。
Note: the code closes DEVNULL
in the parent without waiting for the child process to finish (it has no effect on the child).
注意:代码DEVNULL
在父进程中关闭,无需等待子进程完成(对子进程没有影响)。