[英]How to run an EXE program in the background and get the outuput in python
我想在后台運行一個exe程序
假設程序是 httpd.exe
我可以運行它,但是當我想要輸出時它會卡住,因為如果它成功啟動則沒有 output。 但是如果有錯誤 也沒關系。
這是我正在使用的代碼:
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)
我試圖使以下代碼盡可能通用:
None
記錄寫入隊列以指示 stream 結束。因此隊列的讀者知道在看到兩個這樣的“流結束”指示符之后將不再有行寫入隊列,並且該過程已有效結束。subprocess.Popen
,這樣它也可以內置 shell 命令,也可以使命令的規范更容易(它現在可以是單個字符串而不是字符串列表)。run_cmd
返回創建的進程和隊列。 您現在只需要從隊列中循環讀取行,直到看到兩個None
記錄。 一旦發生這種情況,您就可以等待該過程完成,這應該是立即完成的。subprocess.PIPE
值只有這些輸出之一,然后是從隊列中讀取行的循環應該只尋找一個None
流結束指示器。run_apache
的 run_apache 本身就是一個守護線程。 如果它檢測到來自 Apache 的任何 output,它會設置一個已傳遞給它的事件。 啟動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.