Home >Backend Development >Python Tutorial >Why Does Python's `subprocess.Popen` with `readlines()` Hang, and How Can I Fix It?
Python subprocess readlines() Hangs Issue
Streaming a file and printing output line by line can be achieved using various methods. However, utilizing subprocess with readlines() may lead to hang issues.
Consider the Python script "main.py" designed to stream a Ruby file "ruby_sleep.rb" and print its output.
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")
Executing this script streams the Ruby output as expected, but the readline() method hangs indefinitely, resulting in the "This line is never reached" string never being printed.
Various solutions have been proposed to address this hang issue:
Stdbuf enables 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()
Pexpect can be used for line-based control.
import pexpect pexpect.run("ruby ruby_sleep.rb", logfile=sys.stdout)
PTY allows for providing a tty to enable line-buffering on the Ruby side.
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!")
The above is the detailed content of Why Does Python's `subprocess.Popen` with `readlines()` Hang, and How Can I Fix It?. For more information, please follow other related articles on the PHP Chinese website!