我想从我的python脚本(main.py)
启动一个进程,具体来说我想运行以下命令
`nohup python ./myfile.py &`
并且这个文件myfile.py
应该在我的主要python脚本退出之后。
此外,我希望获得新进程的pid
。
我尝试了os.spawnl*
,os.exec*
&如果我的main.py脚本退出,subprocess.Popen
方法都会终止我的myfile.py
。
我可能会遗漏一些东西。
更新:我可以将os.startfile
与xdg-open
一起使用吗?这是一种正确的方法吗?
示例
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_process
,我看不到任何进程正在运行。
long_process.py 继续打印一些文字:没有退出。
我在这里做错了吗?
答案 0 :(得分:13)
您打开长时间运行的流程并保持管道。所以你希望与它交谈。当yor启动程序脚本退出时,您无法再与它通信。 长时间运行的进程收到 SIGPIPE
并退出。
以下内容对我有用(Linux,Python 2.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
,不要死在它上面。在启动程序进程退出后,没有标准输入。答案 1 :(得分:7)
您可以使用os.fork()
。
import os
pid=os.fork()
if pid==0: # new process
os.system("nohup python ./myfile.py &")
exit()
# parent process continues
答案 2 :(得分:6)
我看不到任何进程正在运行。
您没有看到任何进程正在运行,因为子python
进程会立即退出。 Popen
参数不正确为@user4815162342 says in the comment。
要启动完全独立的流程,您可以使用python-daemon
package或使用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
,而不等待子进程完成(它对子级没有影响)。