ホームページ > バックエンド開発 > Python チュートリアル > プロセス出力の読み取り時に Python プログラムがハングしないようにするにはどうすればよいですか?

プロセス出力の読み取り時に Python プログラムがハングしないようにするにはどうすればよいですか?

Susan Sarandon
リリース: 2024-11-02 13:54:29
オリジナル
530 人が閲覧しました

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

ハングせずに Python でのプロセス出力の読み取りを停止しますか?

問題:

Python プログラムは外部と対話する必要があります継続的に出力を生成するプロセス (「トップ」など)。ただし、出力を直接読み取るだけでは、プログラムが無期限にハングする可能性があります。

解決策:

ハングを防ぐには、次の場合に非ブロッキングまたは非同期メカニズムを採用することが不可欠です。読み取りプロセスの出力。以下に考えられるアプローチをいくつか示します。

スプール一時ファイル (推奨)

このメソッドは、専用のファイル オブジェクトを利用してプロセス出力を保存します。

#! /usr/bin/env python<br>import subprocess<br>import tempfile<br>import time</p>
<p>def main():</p>
<div class="code" style="position:relative; padding:0px; margin:0px;"><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 name == "__main__":

main()
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

スレッドベースの出力読み取り

このアプローチでは、別のスレッドを使用してプロセス出力を継続的に読み取ります。メインスレッドは他のタスクを続行します。

コレクションのインポート<br>サブプロセスのインポート<br>スレッドのインポート<br>インポート時間</p>
<p>def read_output(process, append):</p>
<div class="code" style="position:relative; padding:0px; margin:0px;"><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 name == "__main__":

main()
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

signal.alarm() (Unix のみ)

このメソッドは、Unix シグナルを使用して、すべての出力が読み取られたかどうかに関係なく、指定されたタイムアウト後にプロセスを終了します。

インポート コレクション<br>インポート シグナル<br>インポート サブプロセス</p>
<p>クラス Alarm(Exception):</p>
<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">pass
ログイン後にコピー

def Alarm_handler(signum, Frame):

raise Alarm
ログイン後にコピー

def main():

# 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))
ログイン後にコピー

if name == "__main__":

main()
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

threading.Timer

このアプローチでは、タイマーを使用して、指定されたタイムアウト後にプロセスを終了します。 Unix と Windows システムの両方で動作します。

コレクションのインポート<br>サブプロセスのインポート<br>スレッドのインポート</p>
<p>def main():</p>
<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false"># 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))
ログイン後にコピー

if name == "__main__":

main()
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

スレッドなし、シグナルなし

このメソッドはプロセス出力をチェックし、指定されたタイムアウトを超えた場合にプロセスを強制終了する単純な時間ベースのループ。


インポート コレクション
インポート サブプロセス
インポート sys

インポート時間

def main():
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

== "__main__":
main()
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

注:

保存される行数は、deque データ構造の 'maxlen' パラメーターを設定することで、必要に応じて調整できます。

以上がプロセス出力の読み取り時に Python プログラムがハングしないようにするにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ソース:php.cn
前の記事:Python ジェネレーター オブジェクトを再利用できるように更新できますか? 次の記事:Pandas で CSV ファイルをインポートするときに特定の行をスキップする方法
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
著者別の最新記事
最新の問題
関連トピック
詳細>
人気のおすすめ
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート