'yes' reporting error with subprocess communicate()

command-line, linux, python, shell, subprocess

Solution

The issue is that `subprocess` module before Python 3.2+ doesn't restore `SIGPIPE` signal handler to default action. That is why you get `EPIPE` write error instead.

In Python 3.2+

>>> from subprocess import check_output
>>> check_output("yes | head -3", shell=True)
b'y\ny\ny\n'

`yes` is killed by `SIGPIPE` when `head` exits.

In Python 2:

>>> from subprocess import check_output
>>> check_output("yes | head -3", shell=True)
yes: standard output: Broken pipe
yes: write error
'y\ny\ny\n'

`yes` got `EPIPE` write error. It is safe to ignore the error. It communicates the same information as `SIGPIPE`.

To workaround the problem, you could emulate `restore_signals` in Python 2 using `preexec_fn` parameter :

>>> from subprocess import check_output
>>> import signal
>>> def restore_signals(): # from http://hg.python.org/cpython/rev/768722b2ae0a/
...     signals = ('SIGPIPE', 'SIGXFZ', 'SIGXFSZ')
...     for sig in signals:
...         if hasattr(signal, sig):
...            signal.signal(getattr(signal, sig), signal.SIG_DFL)
... 
>>> check_output("yes | head -3", shell=True, preexec_fn=restore_signals)
'y\ny\ny\n'

Problem

I am using the following function to run a command in Python: ``` def run_proc(cmd): child = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout, stderr = child.communicate() returncode = child.returncode return stdout, stderr, returncode ``` It has always been working fine, however now I'm trying to use the `yes` program to pipe output to stdin. The command I'm trying to run is the following: ``` yes '' | apt-get -y -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" dist-upgrade ``` but I believe it could be substituted with a general example, like: ``` yes | head -3 | cat ``` My problem is that if I try to run any command which has `yes |` in it, the above subprocess.Popen will contain the error messages: ``` yes: standard output: Broken pipe yes: write error ``` For me it seems that the piping still works, as can be seen from `yes | head -3 | cat`'s answer: `y y y`. I have the following questions: - Is the yes piping still functional, even though yes reports error? - How can I fix it?

Original source

Related problems