Art*_*tem 259 python daemon process
我正在尝试将shell脚本移植到更易读的python版本.原始shell脚本在后台使用"&"启动多个进程(实用程序,监视器等).如何在python中实现相同的效果?我希望这些进程不会在python脚本完成时死掉.我确信它与守护进程的概念有某种关系,但我无法轻易找到如何做到这一点.
Dan*_*Dan 343
虽然jkp的解决方案有效,但更新的处理方式(以及文档推荐的方式)是使用该subprocess
模块.对于简单的命令,它是等价的,但是如果你想做一些复杂的事情,它会提供更多选项.
案例示例:
import subprocess
subprocess.Popen(["rm","-r","some.file"])
Run Code Online (Sandbox Code Playgroud)
这应该rm -r somefile
在后台运行. 但要小心:.communicate()
如果python脚本中没有任何内容依赖于正在运行的命令的输出,则只在后台运行一个进程:
例如,以下命令不会在后台运行:
import subprocess
ls_output=subprocess.Popen(["sleep", "30"])
ls_output.communicate() # Will block for 30 seconds
Run Code Online (Sandbox Code Playgroud)
请参阅此处的文档.
另外,澄清一点:"背景"纯粹是一个shell概念:你可能想要的是产生一个新的过程.我在这里使用"背景"来引用类似shell的背景行为,但是不要将其误认为实际存在于后台的进程.
jkp*_*jkp 75
注意:此答案比2009年发布的答案要短.subprocess
现在,在文档中建议使用其他答案中显示的模块
(请注意,子进程模块提供了更强大的工具来生成新进程并检索其结果;使用该模块比使用这些函数更好.)
如果您希望您的进程在后台启动,您可以使用system()
它并以与shell脚本相同的方式调用它,或者您可以spawn
:
import os
os.spawnl(os.P_DETACH, 'some_long_running_command')
Run Code Online (Sandbox Code Playgroud)
(或者,您可以尝试不太便携的os.P_NOWAIT
标志).
Eli*_*ght 45
您可能想要"如何在Python中调用外部命令"的答案.
最简单的方法是使用该os.system
函数,例如:
import os
os.system("some_command &")
Run Code Online (Sandbox Code Playgroud)
基本上,无论你传递给system
函数的是什么,都会像在脚本中将它传递给shell一样执行.
f p*_*f p 29
我在这里找到了这个:
在Windows(win xp)上,父进程在longtask.py
完成其工作之前不会完成.这不是你想要的CGI脚本.问题不是Python特有的,在PHP社区中问题是一样的.
解决方案是将DETACHED_PROCESS
Process Creation Flag传递给CreateProcess
win API中的底层函数.如果你碰巧安装了pywin32,你可以从win32process模块导入标志,否则你应该自己定义:
DETACHED_PROCESS = 0x00000008
pid = subprocess.Popen([sys.executable, "longtask.py"],
creationflags=DETACHED_PROCESS).pid
Run Code Online (Sandbox Code Playgroud)
Jim*_* KD 21
subprocess.Popen()
与close_fds=True
参数一起使用,这将允许衍生的子进程与Python进程本身分离,并在Python退出后继续运行.
https://gist.github.com/yinjimmy/d6ad0742d03d54518e9f
import os, time, sys, subprocess
if len(sys.argv) == 2:
time.sleep(5)
print 'track end'
if sys.platform == 'darwin':
subprocess.Popen(['say', 'hello'])
else:
print 'main begin'
subprocess.Popen(['python', os.path.realpath(__file__), '0'], close_fds=True)
print 'main end'
Run Code Online (Sandbox Code Playgroud)
Ger*_*ncy 12
您可能希望开始调查os模块以分叉不同的线程(通过打开交互式会话并发出帮助(os)).相关函数是fork和任何exec函数.为了让你了解如何启动,在执行fork的函数中放入这样的东西(函数需要将列表或元组'args'作为包含程序名称及其参数的参数;您可能还需要为新线程定义stdin,out和err):
try:
pid = os.fork()
except OSError, e:
## some debug output
sys.exit(1)
if pid == 0:
## eventually use os.putenv(..) to set environment variables
## os.execv strips of args[0] for the arguments
os.execv(args[0], args)
Run Code Online (Sandbox Code Playgroud)
捕获输出并在后台运行 threading
如前所述对这个答案,如果您捕捉输出,stdout=
然后尝试read()
,则过程块。
但是,在某些情况下您需要这样做。例如,我想启动两个进程,它们通过它们之间的端口进行通信,并将它们的stdout保存到日志文件和stdout中。
该threading
模块使我们能够做到这一点。
首先,看看如何在此问题中单独完成输出重定向:Python Popen:同时写入stdout和日志文件
然后:
main.py
#!/usr/bin/env python3
import os
import subprocess
import sys
import threading
def output_reader(proc, file):
while True:
byte = proc.stdout.read(1)
if byte:
sys.stdout.buffer.write(byte)
sys.stdout.flush()
file.buffer.write(byte)
else:
break
with subprocess.Popen(['./sleep.py', '0'], stdout=subprocess.PIPE, stderr=subprocess.PIPE) as proc1, \
subprocess.Popen(['./sleep.py', '10'], stdout=subprocess.PIPE, stderr=subprocess.PIPE) as proc2, \
open('log1.log', 'w') as file1, \
open('log2.log', 'w') as file2:
t1 = threading.Thread(target=output_reader, args=(proc1, file1))
t2 = threading.Thread(target=output_reader, args=(proc2, file2))
t1.start()
t2.start()
t1.join()
t2.join()
Run Code Online (Sandbox Code Playgroud)
sleep.py
#!/usr/bin/env python3
import sys
import time
for i in range(4):
print(i + int(sys.argv[1]))
sys.stdout.flush()
time.sleep(0.5)
Run Code Online (Sandbox Code Playgroud)
运行后:
./main.py
Run Code Online (Sandbox Code Playgroud)
标准输出每0.5秒更新一次,每两行包含一次:
0
10
1
11
2
12
3
13
Run Code Online (Sandbox Code Playgroud)
每个日志文件都包含给定进程的相应日志。
灵感来源:https : //eli.thegreenplace.net/2017/interacting-with-a-long-running-child-process-in-python/
已在Ubuntu 18.04,Python 3.6.7上测试。
归档时间: |
|
查看次数: |
372562 次 |
最近记录: |