Rumah >pembangunan bahagian belakang >Tutorial Python >Mengapakah `subprocess.Popen` Python dengan `readlines()` Hang, dan Bagaimana Saya Boleh Membetulkannya?

Mengapakah `subprocess.Popen` Python dengan `readlines()` Hang, dan Bagaimana Saya Boleh Membetulkannya?

DDD
DDDasal
2024-12-03 10:37:10218semak imbas

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

Python subprocess readlines() Hangs Issue

Pengenalan

Strim fail dan mencetak output baris demi baris boleh dicapai menggunakan pelbagai kaedah. Walau bagaimanapun, menggunakan subproses dengan readlines() boleh membawa kepada isu hang.

Skrip Python

Pertimbangkan skrip Python "main.py" yang direka untuk menstrim fail Ruby "ruby_sleep.rb" dan mencetak outputnya.

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")

Masalah dan Pemerhatian

Melaksanakan ini skrip menstrim keluaran Ruby seperti yang dijangkakan, tetapi kaedah readline() tergantung selama-lamanya, menyebabkan rentetan "Barisan ini tidak pernah dicapai" tidak pernah dicetak.

Pendekatan Penyelesaian

Pelbagai penyelesaian telah dicadangkan untuk menangani isu hang ini:

1. Menggunakan Stdbuf

Stdbuf mendayakan penimbalan talian dalam mod bukan interaktif.

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. Menggunakan Peexpect

Pexpect boleh digunakan untuk kawalan berasaskan talian.

import pexpect

pexpect.run("ruby ruby_sleep.rb", logfile=sys.stdout)

3. Menggunakan PTY

PTY membolehkan menyediakan tty untuk mendayakan penimbal talian pada bahagian 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!")

Atas ialah kandungan terperinci Mengapakah `subprocess.Popen` Python dengan `readlines()` Hang, dan Bagaimana Saya Boleh Membetulkannya?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn