Default encoding for python for stderr? Default encoding for python for stderr? bash bash

Default encoding for python for stderr?


You can silence stderr by binding it to a custom writer:

#!/usr/bin/env pythonimport codecs, sysclass NullWriter:    def write(self, *args, **kwargs):        passif len(sys.argv) == 2:   if sys.argv[1] == '1':      sys.stderr = NullWriter()   elif sys.argv[1] == '2':      #NOTE: sys.stderr.encoding is *read-only*       #      therefore the whole stderr should be replaced      # encode all output using 'utf8'      sys.stderr = codecs.getwriter('utf8')(sys.stderr)print >>sys.stderr, u"\u20AC" # euro signprint "ok"

Example:

$ python silence_stderr.pyTraceback (most recent call last):  File "silence_stderr.py", line 11, in <module>    print >>sys.stderr, u"\u20AC"UnicodeEncodeError: 'ascii' codec can't encode character u'\u20ac' in position 0: ordinal not in range(128)

Silenced stderr:

$ python silence_stderr.py 1ok

Encoded stderr:

$ python silence_stderr.py 2€ok

NOTE: I've got the above outputs inside emacs therefore to emulate it in a terminal you could do:

$ python ... 2>out.txt$ cat out.txt

NOTE: Inside Windows console (after chcp 65001 that switch to 'utf-8' and with truetype font (Lucida Console)) I've got strange results:

C:\> python silence_stderr.py 2Traceback (most recent call last):  File "silence_stderr.py", line 14, in <module>    print >>sys.stderr, u"\u20AC" # euro sign  File "C:\pythonxy\python\lib\codecs.py", line 304, in write    self.stream.write(data)IOError: [Errno 13] Permission denied

If the font is not truetype then the exception doesn't raise but the output is wrong.

Perl works for the truetype font:

C:\> perl  -E"say qq(\x{20ac})"Wide character in print at -e line 1.€

Redirection works though:

C:\>python silence_stderr.py 2 2>tmp.logokC:\>cat tmp.log€cat: write error: Permission denied

re comment

From codecs.getwriter documentation:

Look up the codec for the given encoding and return its StreamWriter class or factory function. Raises a LookupError in case the encoding cannot be found.

An oversimplified view:

class UTF8StreamWriter:    def __init__(self, writer):        self.writer = writer    def write(self, s):        self.writer.write(s.encode('utf-8'))sys.stderr = UTF8StreamWriter(sys.stderr)


When stderr is not redirected, it takes on the encoding of your terminal. This all goes out the door when you redirect it though. You'll need to use sys.stderr.isatty() in order to detect if it's redirected and encode appropriately.


You could also just encode the string as ASCII, replacing unicode characters that don't map. Then you don't have to worry about what kind of terminal you have.

asciiTitle = page_title.encode("ascii", "backslashreplace")print >>sys.stderr, "bad page title", asciiTitle

That replaces the characters that can't be encoded with backslash-escapes, i.e. \xfc. There are some other replace options too, described here:

http://docs.python.org/library/stdtypes.html#str.encode