如何避免 Python 程式在讀取進程輸出時掛起?

Susan Sarandon
發布: 2024-11-02 13:54:29
原創
428 人瀏覽過

How to Avoid Python Programs from Hanging When Reading Process Output?

停止讀取 Python 中的進程輸出而不掛起?

問題:

Python 程式需要與外部互動連續產生輸出的過程(例如「上」)。但是,直接讀取輸出可能會導致程式無限期掛起。

解決方案:

為了防止掛起,必須在以下情況下採用非阻塞或非同步機制:讀取過程輸出。以下是一些可能的方法:

假脫機暫存檔案(建議)

此方法利用專用檔案物件來儲存進程輸出。

#! /usr/bin/env python<br>導入子程序<br>導入臨時檔案<br>導入時間<p>def main():</p><pre class="brush:php;toolbar:false"># Open a temporary file (automatically deleted on closure)
f = tempfile.TemporaryFile()

# Start the process and redirect stdout to the file
p = subprocess.Popen(["top"], stdout=f)

# Wait for a specified duration
time.sleep(2)

# Kill the process
p.terminate()
p.wait()

# Rewind and read the captured output from the file
f.seek(0)
output = f.read()

# Print the output
print(output)
f.close()
登入後複製

if 名稱 == "__main__":

main()
登入後複製
登入後複製
登入後複製
登入後複製

基於執行緒的輸出讀取

這種方法採用單獨的執行緒來連續讀取進程輸出,同時主執行緒繼續執行其他任務。

導入集合<br>導入子程序<br>導入執行緒<br>導入時間<p>def read_output(process,append):</p><pre class="brush:php;toolbar:false">for line in iter(process.stdout.readline, ""):
    append(line)
登入後複製

def main():
# Start the process and redirect stdout
process = subprocess.Popen(["top"], stdout=subprocess.PIPE, close_fds=True)

# Create a thread for output reading
q = collections.deque(maxlen=200)
t = threading.Thread(target=read_output, args=(process, q.append))
t.daemon = True
t.start()

# Wait for the specified duration
time.sleep(2)

# Print the saved output
print(''.join(q))
登入後複製

if 名稱

== "__main__":
main()
登入後複製
登入後複製
登入後複製
登入後複製


al.alarm ()(僅限Unix)

此方法使用Unix 訊號在指定逾時後終止進程,無論是否已讀取所有輸出。

導入集合<pre class="brush:php;toolbar:false">pass
登入後複製
導入訊號

導入子程序

raise Alarm
登入後複製
class Alarm(Exception):

# Start the process and redirect stdout
process = subprocess.Popen(["top"], stdout=subprocess.PIPE, close_fds=True)

# Set signal handler
signal.signal(signal.SIGALRM, alarm_handler)
signal.alarm(2)

try:
    # Read and save a specified number of lines
    q = collections.deque(maxlen=200)
    for line in iter(process.stdout.readline, ""):
        q.append(line)
    signal.alarm(0)  # Cancel alarm
except Alarm:
    process.terminate()
finally:
    # Print the saved output
    print(''.join(q))
登入後複製
def Alarm_handler(signum,🎜>

def Alarm_handler(signum,,) :

main()
登入後複製
登入後複製
登入後複製
登入後複製
def main():

if

名稱

== "__main__":


== "__main__":

# Start the process and redirect stdout
process = subprocess.Popen(["top"], stdout=subprocess.PIPE, close_fds=True)

# Create a timer for process termination
timer = threading.Timer(2, process.terminate)
timer.start()

# Read and save a specified number of lines
q = collections.deque(maxlen=200)
for line in iter(process.stdout.readline, ""):
    q.append(line)
timer.cancel()

# Print the saved output
print(''.join(q))
登入後複製
threading.Timer

此方法使用計時器在指定的逾時後終止程序。它適用於 Unix 和 Windows 系統。

導入集合<div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">main()
登入後複製
登入後複製
登入後複製
登入後複製
導入子程序

導入執行緒

def main():

if

name


if

name

args = sys.argv[1:]
if not args:
    args = ['top']

# Start the process and redirect stdout
process = subprocess.Popen(args, stdout=subprocess.PIPE, close_fds=True)

# Save a specified number of lines
q = collections.deque(maxlen=200)

# Set a timeout duration
timeout = 2

now = start = time.time()
while (now - start) < timeout:
    line = process.stdout.readline()
    if not line:
        break
    q.append(line)
    now = time.time()
else:  # On timeout
    process.terminate()

# Print the saved output
print(''.join(q))
登入後複製
if

name

if
main()
登入後複製
登入後複製
登入後複製
登入後複製
name

if name

if 名稱 == "__main__":沒有線程,沒有訊號此方法使用簡單的基於時間的循環,用於檢查進程輸出,如果超過指定逾時則將其終止。
導入集合導入子程序導入系統導入時間 def main():if 名稱 == "__main__":
登入後複製
注意:儲存的行數可以依照需要透過設定deque資料結構的'maxlen'參數來調整。

以上是如何避免 Python 程式在讀取進程輸出時掛起?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

來源:php.cn
上一篇:能否讓 Python 生成器物件煥然一新以供重用? 下一篇:使用 Pandas 匯入 CSV 檔案時如何跳過特定行?
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
作者最新文章
最新問題
關於CSS心智圖的課件在哪? 課件
來自於 2024-04-16 10:10:18
0
0
1549
相關專題
更多>
熱門推薦
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!