[Python-ideas] Replacing the standard IO streams (was Re: changing sys.stdout encoding)

Victor Stinner victor.stinner at gmail.com
Tue Jun 12 23:44:00 CEST 2012


>>     sys.stdin = open(sys.stdin.fileno(), 'r',<new settings>)
>>     sys.stdout = open(sys.stdout.fileno(), 'w',<new settings>)
>>     sys.stderr = open(sys.stderr.fileno(), 'w',<new settings>)
>
>
>    sys.stdin = io.TextIOWrapper(sys.stdin.detach(), <new settings>)
>    sys.stdout = io.TextIOWrapper(sys.stdout.detach(), <new settings>)
>    ...
>
> None of these methods are not guaranteed to work if the input or output have
> occurred before.

You should set the newline option for sys.std* files. Python 3 does
something like this:

if os.name == "win32:
   # translate "\r\n" to "\n" for sys.stdin on Windows
   newline = None
else:
   newline = "\n"
sys.stdin = io.TextIOWrapper(sys.stdin.detach(), newline=newline, <new
settings>)
sys.stdout = io.TextIOWrapper(sys.stdout.detach(), newline="\n", <new settings>)
sys.stderr = io.TextIOWrapper(sys.stderr.detach(), newline="\n", <new settings>)

--

Lib/test/regrtest.py uses the following code which is not exactly
correct (it creates a new buffered writer instead of reusing
sys.stdout buffered writer):

def replace_stdout():
    """Set stdout encoder error handler to backslashreplace (as stderr error
    handler) to avoid UnicodeEncodeError when printing a traceback"""
    import atexit

    stdout = sys.stdout
    sys.stdout = open(stdout.fileno(), 'w',
        encoding=stdout.encoding,
        errors="backslashreplace",
        closefd=False,
        newline='\n')

    def restore_stdout():
        sys.stdout.close()
        sys.stdout = stdout
    atexit.register(restore_stdout)

Victor



More information about the Python-ideas mailing list