pythonbashpippipe

Why does "pip list" not like broken pipes on the bash command line?


I'm using a bash terminal.

I just wanted to peek at the first few names of installed python packages:

pip list | head -n5

And got an error message:

Package            Version
------------------ ----------------
attrs              21.2.0
Automat            20.2.0
Babel              2.8.0
ERROR: Pipe to stdout was broken
Exception ignored in: <_io.TextIOWrapper name='<stdout>' mode='w' encoding='utf-8'>
BrokenPipeError: [Errno 32] Broken pipe

Is something broken? If I'm going to capture that information programmatically, I definitely don't want an error message included.


Solution

  • Is something broken?

    Not in the sense you mean.

    The head command terminates after it copies the the specified number of initial lines from its input to its output. This is normal and expected.

    If the input is coming from another command via a pipe, and that command attempts to write additional data when there is no longer anything on the consuming end of the pipe, then the system reports an error to it. The conventional terminology for this kind of error is a "broken pipe". This also is normal and expected. It is an error from the perspective of the program receiving it because it prevents the program from completing writing its output.

    It is up to the program receiving such an error what to do with it. When that program is a Python interpreter, it responds by throwing a BrokenPipeError, which the Python program has the opportunity to handle in a way appropriate to it. Oftentimes the most appropriate thing to do with that or another OSError is nothing, so that it rises all the way to the top level and causes Python to terminate. That is what pip has done.

    If I'm going to capture that information programmatically, I definitely don't want an error message included.

    This is why the system provides two standard streams for output:

    Programs are in control of what data they write to each, but you can generally expect that they will write error messages to standard error. The Python interpreter indeed does this. When you run a program interactively in the terminal, both standard output and standard error default to writing data to the terminal, but they can be captured or redirected independently. That's one of the main reasons for maintaining a separation in the first place.