There is a known issue in Python, where \"close failed in file object destructor\" when \"Broken pipe\" happens on stdout - Python tracker Issue 11380; also seen in python - Why
This error message is Python indicating that the supplied pipeline definition is broken, albeit in a somewhat confusing way (see http://bugs.python.org/issue11380)
echo doesn't actually accept input via stdin, so the input pipe from Python ends up being closed early. The extra exception you're seeing (outside the exception handler) is then due to the implicit attempt to flush the standard streams as the interpreter is shutting down. This happens outside the scope of any user provided Python code, so the interpreter just writes the error to stderr
rather than invoking normal exception processing.
If you know you don't care about broken pipes for your use case, you can deal with this case by explicitly closing stdout
before the end of your program. It will still complain about the broken pipe, but it will do it in a way that lets you catch and suppress the exception as usual:
import sys
def main():
teststr = "Hello " * 5
try:
sys.stdout.write(teststr + "\n")
sys.stdout.flush()
except IOError:
sys.stderr.write("Exc: " + str(sys.exc_info()[0]) + "\n")
try:
sys.stdout.close()
except IOError:
sys.stderr.write("Exc on close: " + str(sys.exc_info()[0]) + "\n")
if __name__ == "__main__":
main()
In this version, only the expected output is seen, because even the attempt at closing it is enough to ensure the stream is already marked as closed during interpreter shutdown:
$ python3 testprint.py | echo
Exc:
Exc on close: