Home > Backend Development > Python Tutorial > Why Does `subprocess.readlines()` Hang When Streaming a Ruby File in Python?

Why Does `subprocess.readlines()` Hang When Streaming a Ruby File in Python?

Mary-Kate Olsen
Release: 2024-12-06 12:59:15
Original
912 people have browsed it

Why Does `subprocess.readlines()` Hang When Streaming a Ruby File in Python?

Python subprocess.readlines() hangs

Problem:

In the following Python code, using subprocess.readlines() to stream a Ruby file causes the program to hang indefinitely, preventing the final print statement from being executed:

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

file_path = '/Users/luciano/Desktop/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 is never reached!")
Copy after login

Cause:

The issue here stems from the use of pty, which is intended for pseudo-terminal handling. This typically causes line-buffering on the Ruby side, resulting in the readline() function waiting indefinitely for a newline character.

Solutions:

There are several options to resolve this issue:

1. Using pexpect:

pexpect enables line-buffering in a non-interactive setting:

import sys
import pexpect

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

2. Using stdbuf:

stdbuf can be used to enable line-buffering in non-interactive mode:

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()
Copy after login

3. Using pty from the standard library:

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

master_fd, slave_fd = pty.openpty()  # provide tty to enable
                                     # line-buffering on ruby's side
proc = Popen(['ruby', 'ruby_sleep.rb'],
             stdin=slave_fd, stdout=slave_fd, stderr=STDOUT, close_fds=True)
os.close(slave_fd)
try:
    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!")
Copy after login

The above is the detailed content of Why Does `subprocess.readlines()` Hang When Streaming a Ruby File in Python?. For more information, please follow other related articles on the PHP Chinese website!

source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Latest Articles by Author
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template