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)
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: