[英]Python: executing a long-running process with subprocess.Popen, killing it, and accessing to its output
[英]Start child process with subprocess.Popen and read its output while it is running
我有一个命令,该命令的输出将写入文件并使用subprocess.Popen
调用该命令。 这是一个示例:
stdout_output = open('testfile.txt','w')
process = subprocess.Popen(command,stdout=stdout_output,shell=True)
stdout_read = open('testfile.txt','r')
data = stdout_read.read()
print data
数据有时没有任何内容,但是当我在触发过程和读取数据之间添加一些睡眠时,例如
stdout_output = open('testfile.txt','w')
process = subprocess.Popen(command,stdout=stdout_output,shell=True)
time.sleep(3)
stdout_read = open('testfile.txt','r')
data = stdout_read.read()
print data
然后,数据包含写入文件的实际数据。 这里有我想念的东西吗? 还是有其他方法可以在触发过程和读取输出之间增加一些时间,而不是提供硬编码的睡眠。
注 -该命令正在进行中。 我无法添加process.wait()
或无法等待进程完成后再读取文件。
Popen
启动一个同时运行的新进程,因此,如果要可靠地获取该进程的输出,则必须等待该进程。 实际上, subprocess
模块具有一个check_output
函数,可以为您执行此操作:
data = subprocess.check_output(command, shell=True)
print data
显然,这是阻碍。
“等待”进程结束而不阻塞主进程的唯一方法是poll
它。 但是,这要求您以定期检查的方式编写代码,并且当poll
方法返回不同于None
您可以读取过程的输出。
例如:
def do_stuff(proc, filename):
# proc.poll() check if proc has ended
while proc.poll() is None:
print('Here you do whatever you want while you wait for the process')
# do other stuff
ping_pong.play()
# here we are sure the command terminate and wrote his output
proc.stdout.close()
with open(filename) as f:
return f.read()
stdout_file = open('some_file', 'w')
process = Popen(['command'], stdout=stdout_file)
output = do_stuff(process, 'some_file')
根据您正在执行的操作,您可能需要以不同的方式构造代码。
缓冲可能是个问题。
尝试打开文件以使用零长度缓冲区进行写入。 像这样:
stdout_output = open('testfile.txt','w', 0)
当然,命令可能不会立即产生输出,在这种情况下,您将需要有一个循环以不断尝试读取。
由于您希望能够在启动过程后立即阅读,因此可以使用Pipe
。 subprocess.Popen
已经为您提供了一个选项,把stdint/stdout/stderr
穿过。
这是带有示例bash
脚本的Python代码示例,该脚本回显消息,休眠然后回显另一条消息。 请注意,Python代码必须知道子进程何时完成发送数据。
import subprocess
"""
notifier.sh
------------------
echo "This is me"
sleep 4
echo "This is me again"
------------------
"""
command = ['bash', 'notifier.sh']
process = subprocess.Popen(command, stdout=subprocess.PIPE)
while True:
if process.poll() is not None:
break
data = process.stdout.readline()
print data
我确实尝试通过此示例bash
shell脚本来模拟用例。
另外,我确实删除了shell=True
因为我不确定是否有充分的理由使用它,但这是一个很大的安全问题。
如果您不希望等到执行结束,则选项之一是在单独的线程中读取:
def reader(fd, finished):
while not finished.is_set():
data = fd.read()
if data: print(data)
time.sleep(SOME_TIMEOUT)
process = subprocess.Popen(command,stdout=stdout_output,shell=True)
finished = threading.Event()
reader_thread = threading.Thread(target=reader, args=(stdout_output, finished))
reader_thread.start()
process.wait()
finished.set()
reader_thread.join()
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.