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
Lepaskan: 2024-12-03 10:37:10
asal
141 orang telah melayarinya

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")
Salin selepas log masuk

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()
Salin selepas log masuk

2. Menggunakan Peexpect

Pexpect boleh digunakan untuk kawalan berasaskan talian.

import pexpect

pexpect.run("ruby ruby_sleep.rb", logfile=sys.stdout)
Salin selepas log masuk

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!")
Salin selepas log masuk

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!

sumber:php.cn
Kenyataan Laman Web ini
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
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan