首頁 > 後端開發 > Python教學 > 為什麼 Python 的 `subprocess.Popen` 和 `readlines()` 會掛起,如何修復它?

為什麼 Python 的 `subprocess.Popen` 和 `readlines()` 會掛起,如何修復它?

DDD
發布: 2024-12-03 10:37:10
原創
141 人瀏覽過

Why Does Python's `subprocess.Popen` with `readlines()` Hang, and How Can I Fix It?

Python子程序readlines()掛起問題

簡介

可以實作串流傳輸檔案並逐行列印檔案輸出使用各種方法。然而,使用帶有 readlines() 的子程序可能會導致掛起問題。

Python 腳本

考慮設計用於串流 Ruby 檔案「ruby_sleep.rb」的 Python 腳本「main.py」和列印其輸出。

import pty
import os
from subprocess import Popen, PIPE, STDOUT

file_path = '/path/to/ruby_sleep.rb'
command = ' '.join(["ruby", file_path])

master, slave = pty.openpty()
proc = Popen(command, bufsize=0, shell=True, stdout=slave, stderr=slave, close_fds=True)     
stdout = os.fdopen(master, 'r', 0)

while proc.poll() is None:
    data = stdout.readline()
    if data != "":
        print(data)
    else:
        break

print("This line is never reached")
登入後複製

問題和觀察

執行此腳本按預期流式傳輸Ruby 輸出,但readline() 方法無限期掛起,導致「永遠無法到達此行」字串永遠不會被列印。

解決方案

已提出各種解決方案來解決此掛起問題:

1.利用Stdbuf

Stdbuf 可以在非交互模式下啟用行緩衝。

from subprocess import Popen, PIPE, STDOUT

proc = Popen(['stdbuf', '-oL', 'ruby', 'ruby_sleep.rb'],
             bufsize=1, stdout=PIPE, stderr=STDOUT, close_fds=True)
for line in iter(proc.stdout.readline, b''):
    print line,
proc.stdout.close()
proc.wait()
登入後複製

2.使用 Pexpect

Pexpect 可用於基於行的控制。

import pexpect

pexpect.run("ruby ruby_sleep.rb", logfile=sys.stdout)
登入後複製

3.使用 PTY

PTY 允許提供 tty 以在 Ruby 端啟用行緩衝。

import os
import pty
from subprocess import Popen, STDOUT

master_fd, slave_fd = pty.openpty()
proc = Popen(['ruby', 'ruby_sleep.rb'],
             stdin=slave_fd, stdout=slave_fd, stderr=STDOUT, close_fds=True)
os.close(slave_fd)
while 1:
    try:
        data = os.read(master_fd, 512)
    except OSError as e:
        if e.errno != errno.EIO:
            raise
        break # EIO means EOF on some systems
    else:
        if not data: # EOF
            break
        print('got ' + repr(data))
finally:
    os.close(master_fd)
    if proc.poll() is None:
        proc.kill()
    proc.wait()
    print("This is reached!")
登入後複製

以上是為什麼 Python 的 `subprocess.Popen` 和 `readlines()` 會掛起,如何修復它?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板