[英]How to run an EXE program in the background and get the outuput in python
I want to run an exe program in the background我想在后台运行一个exe程序
Let's say the program is httpd.exe假设程序是 httpd.exe
I can run it but when I want to get the outupt It get stuck becuase there is no output if It starts successfully.我可以运行它,但是当我想要输出时它会卡住,因为如果它成功启动则没有 output。 But if there is an error It's OK.但是如果有错误 也没关系。
Here is the code I'm using:这是我正在使用的代码:
import asyncio
import os
os.chdir('c:\\apache\\bin')
process, stdout, stderr = asyncio.run(run('httpd.exe'))
print(stdout, stderr)
async def run(cmd):
proc = await asyncio.create_subprocess_exec(
cmd,
stdout=asyncio.subprocess.PIPE,
stderr=asyncio.subprocess.PIPE)
stdout, stderr = await proc.communicate()
return (proc, stdout, stderr)
I tried to make the following code as general as possible:我试图使以下代码尽可能通用:
None
record to the queue to indicate end of stream. So the reader of the queue know that after seeing two such "end of stream" indicators that there will be no more lines being written to the queue and that the process has effectively ended.当在每个 stdout 和 stderr 上遇到流结束时,线程将一个特殊的None
记录写入队列以指示 stream 结束。因此队列的读者知道在看到两个这样的“流结束”指示符之后将不再有行写入队列,并且该过程已有效结束。subprocess.Popen
can be made with argument shell=True so that this can also built-in shell commands and also to make the specification of the command easier (it can now be a single string rather than a list of strings).可以使用参数shell=True调用subprocess.Popen
,这样它也可以内置 shell 命令,也可以使命令的规范更容易(它现在可以是单个字符串而不是字符串列表)。run_cmd
returns the created process and the queue. function run_cmd
返回创建的进程和队列。 You just have to now loop reading lines from the queue until two None
records are seen.您现在只需要从队列中循环读取行,直到看到两个None
记录。 Once that occurs, you can then just wait for the process to complete, which should be immediate.一旦发生这种情况,您就可以等待该过程完成,这应该是立即完成的。subprocess.PIPE
value for only one of these outputs and then the loop that is reading lines from the queue should only be looking for one None
end-of-stream indicator.如果您知道您正在启动的进程只将其 output 写入 stdout 或 stderr(或者如果您只想捕获这些输出之一),那么您可以修改程序以仅启动一个线程并指定subprocess.PIPE
值只有这些输出之一,然后是从队列中读取行的循环应该只寻找一个None
流结束指示器。run_apache
, which runs Apache as a subprocess, is itself a daemon thread.作为子进程运行run_apache
的 run_apache 本身就是一个守护线程。 If it detects any output from Apache, it sets an event that has been passed to it.如果它检测到来自 Apache 的任何 output,它会设置一个已传递给它的事件。 The main thread that starts run_apache
can periodically test this event, wait on this event, wait for the run_apache
thread to end (which will only occur when Apache ends) or can terminate Apache via global variable proc
.启动run_apache
的主线程可以定期测试这个事件,等待这个事件,等待run_apache
线程结束(这只会在 Apache 结束时发生)或者可以通过全局变量proc
终止 Apache。import subprocess
import sys
import threading
import queue
def read_stream(f, q):
for line in iter(f.readline, ''):
q.put(line)
q.put(None) # show no more data from stdout or stderr
def run_cmd(command, run_in_shell=True):
"""
Run command as a subprocess. If run_in_shell is True, then
command is a string, else it is a list of strings.
"""
proc = subprocess.Popen(command, shell=run_in_shell, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
q = queue.Queue()
threading.Thread(target=read_stream, args=(proc.stdout, q), daemon=True).start()
threading.Thread(target=read_stream, args=(proc.stderr, q), daemon=True).start()
return proc, q
import os
def run_apache(event):
global proc
os.chdir('c:\\apache\\bin')
proc, q = run_cmd(['httpd.exe'], False)
seen_None_count = 0
while seen_None_count < 2:
line = q.get()
if line is None:
# end of stream from either stdout or stderr
seen_None_count += 1
else:
event.set() # Seen output line:
print(line, end='')
# wait for process to terminate, which should be immediate:
proc.wait()
# This event will be set if Apache write output:
event = threading.Event()
t = threading.Thread(target=run_apache, args=(event,), daemon=True)
t.start()
# Main thread runs and can test event any time to see if it has done any output:
if event.is_set():
...
# The main thread can wait for run_apache thread to normally terminate,
# will occur when Apache terminates:
t.join()
# or the main thread can kill Apache via global variable procL
proc.terminate() # No need to do t.join() since run_apache is a daemon thread
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.