睿智的椰子 · JDBC连接oracle11g——socke ...· 3 月前 · |
淡定的核桃 · python ...· 5 月前 · |
道上混的上铺 · SpringBoot | ...· 9 月前 · |
爱运动的木瓜 · npm通过--registry来指定安装源 ...· 1 年前 · |
爽快的汽水 · javascript - Having ...· 1 年前 · |
我正在尝试将shell脚本移植到更具可读性的python版本。原始shell脚本启动几个进程(实用程序、监视器等)在"&“的背景中。如何在python中实现同样的效果?当python脚本完成时,我希望这些进程不要死。我确信这与守护进程的概念有某种关系,但我无法轻松地找到如何做到这一点。
您可能想知道 “如何在Python中调用外部命令” 的答案。
最简单的方法是使用
os.system
函数,例如:
import os
os.system("some_command &")
基本上,传递给
system
函数的任何内容都将被执行,就像在脚本中将它传递给shell一样。
您可能希望开始研究用于分叉不同线程的os模块(通过打开交互式会话并发出帮助(Os))。相关的函数是叉子和任何一个执行函数。要让您了解如何开始,请将类似的内容放在执行叉的函数中(函数需要接受一个列表或元组'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)
虽然
jkp
的解决方案起作用,但新的处理方法(以及文档推荐的方式)是使用
subprocess
模块。对于简单的命令,它的等效性,但如果您想做一些复杂的事情,它提供了更多的选项。
例如,您的案例:
import subprocess
subprocess.Popen(["rm","-r","some.file"])
这将在后台运行
rm -r some.file
。请注意,对从
.communicate()
返回的对象调用
Popen
将被阻塞,直到它完成为止,所以如果您希望它在后台运行,就不要这样做:
import subprocess
ls_output=subprocess.Popen(["sleep", "30"])
ls_output.communicate() # Will block for 30 seconds
请参阅文档 这里 。
另外,需要澄清的一点是:在这里使用“后台”纯粹是一个shell概念;从技术上讲,您的意思是在等待进程完成时,您希望在不阻塞的情况下生成一个进程。但是,我在这里使用了“背景”来指类似shell的行为。
我找到了这个 这里
在windows (win xp)上,父进程在
longtask.py
完成其工作之前不会完成。这不是你想要的CGI-脚本。这个问题并不是Python特有的,在PHP社区中,问题是一样的。
解决方案是将
DETACHED_PROCESS
过程创建旗
传递给win API中的底层
CreateProcess
函数。如果您碰巧安装了pywin32,您可以从win32process模块导入标志,否则您应该自己定义它:
DETACHED_PROCESS = 0x00000008
pid = subprocess.Popen([sys.executable, "longtask.py"],
creationflags=DETACHED_PROCESS).pid
将
subprocess.Popen()
与
close_fds=True
参数一起使用,它将允许派生的子进程与process本身分离,并在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'
threading
既捕获输出,又在后台运行
正如前面提到的
关于这个答案
,如果您用
stdout=
捕获输出,然后尝试使用
read()
,那么流程就会阻塞。
但是,有些情况下您需要这样做。例如,我希望启动 两个进程通过它们之间的一个端口进行对话 ,并将它们的stdout保存到日志文件和stdout中。
模块 允许我们这样做。
首先,看看如何单独完成输出重定向部分的问题: Python :同时写入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()
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)
跑完后:
./main.py
stdout每0.5秒更新一次,每两行包含:
0