[Python-Dev] Unicode print/stdoutput exceptions are not nice

Robert Kiendl rkiendl at gmx.net
Thu Jan 12 11:18:43 CET 2006


<1137059888.538391.119110 at o13g2000cwo.googlegroups.com>
Martin v. Löwis schrieb:

 > Robert wrote:
 > > is in a PythonWin Interactive session - ok results for cyrillic chars
 > > (tolerant mbcs/utf-8 encoding!).
 > > But if I do this on Win console (as you probably mean), I get also
 > > encoding Errors - no matter if chcp1251, because cyrillic chars raise
 > > the encoding errors also.
 >
 > If you do "chcp 1251" (not "chcp1251") in the console, and then
 > run python.exe in the same console, what is the value of
 > sys.stdout.encoding?

correctly: 'cp1252' in my case; cyrillic-chars break "print"   (on PC 
linux 2.2 tty py24 sys.stdout.encoding is None (?); only 
locale.getdef... useful? )

I live with this in site(customize):

import codecs
_stdout=sys.stdout
if sys.platform=='win32' and not 
sys.modules.has_key('pywin.framework.startup'):
     _stdoutenc=getattr(_stdout,'encoding',None) or sys.getdefaultencoding()
     try: codecs.lookup(_stdoutenc)
     except LookupError: _stdoutenc=sys.getdefaultencoding()
     class StdOut:
         def write(self,s): 
_stdout.write(s.encode(_stdoutenc,'backslashreplace'))
     sys.stdout=StdOut()
elif sys.platform.startswith('linux'):
     import locale
     _stdoutenc=locale.getdefaultlocale()[1]
     try: codecs.lookup(_stdoutenc)
     except LookupError: _stdoutenc=sys.getdefaultencoding()
     class StdOut:
         def write(self,s): 
_stdout.write(s.encode(_stdoutenc,'backslashreplace'))
     sys.stdout=StdOut()


 > > I think this is not a good behaviour of python to be so picky.
 >
 > I think it it is good.
 >
 >    Errors should never pass silently.
 >    Unless explicitly silenced.

A political question. Arguments:

* Webbrowsers for example have to display defective HTML as good as 
possible, unknown unicode chars as "?" and so on... Users got very angry 
in the beginning of browsers when 'strict' programmers displayed their 
exception error boxes ...

* at least the "print" statement has to go through - the costs (for 
angry users and developers; e.g. 
http://blog.ianbicking.org/do-i-hate-unicode-or-do-i-hate-ascii.html) 
are much higher when apps suddenly break in simple print/display-output 
when the system picks up alien unicode chars somewhere (e.g. 
occasionally in filenames,...). No one is really angry when occasionally 
chinese chars are displayed cryptically on non-chinese computers. One 
can investigate, add fonts, ... to improve, or do nothing in most cases, 
but apps do not break on every print statement! This is not only true 
for tty-output, but also for log-file redirect and almost any common 
situation for print/normal stdout/file-(write)-output.

* anything is nice-printable in python by default, why not 
unicode-strings!? If the decision for default 'strict' encoding on 
stdout stands, we have at least to discuss about print-repr for unicode.

* the need for having technical strings 'strict' is much more rare. And 
programmers are anyway very aware in such situations . e.g. by 
asciifile.write( us.encode(xy,'strict') )   .

* on Windows for example the (good) mbcs_encode is anyway tolerant as 
it: unkown chars are mapped to '?' . I never had any objection to this.

Some recommendations - soft to hard:

* make print-repr for unicode strings tolerant  (and in PythonWin alwasy 
tolerant 'mbcs' encoding)

* make stdout/files to have 'replace'-mode encoding by default. (similar 
as done with my code above)

* set site.py/encoding=('ascii', 'replace')   # if not utf-8/mbcs/locale 
;enable a tuple
* save sys._setdefaultencoding by default

* I would also live perfectly with .encode(enc) to run 'replace' by 
default, and 'strict' on demand. None of my apps and scripts would break 
because of this, but win. A programmer is naturally very aware when he 
wants 'strict'. Can you name realistic cases where 'replace' behavior 
would be so critical that a program damages something?


 > > In
 > > 1136925967.990106.299760 at g44g2000cwa.googlegroups.com I showed, how I
 > > solved this so far. Any better/portable idea?
 >
 > Not sure why you aren't using sys.stdout.encoding on Linux. I would do
 >
 > try:
 >   c = codecs.getwriter(sys.stdout.encoding)
 > except:
 >   c = codecs.getwriter('ascii')
 > sys.stdout = c(sys.stdout, 'replace')
 >
 > Also, I wouldn't edit site.py, but instead add sitecustomize.py.

I have more problems with the shape of sys.path in different situations, 
multiple sitecustomize.py on other apps, environments, OS / users, 
cxfreeze,py2exe  ...   sitecustomize not stackable easily: a horror 
solution. The need is for a callable _function_ or for general change in 
python behaviour.

modifiying site.py is better and stable for me (I have my 
patch/module-todo-list handy each time i install a new python), as I 
always want tolerant behaviour. in code i check for 
site.encoding/_setdefaultencoding (I save this). Thus i get one central 
error if setup is not correct, but not evil unicode-errors somewhere 
deep in the app once on a russian computer in the future...

 > > Yes. But the original problem is, that occasionally unicode strings
 > > (filenames in my case) arise which are not defined in the local
 > > platform encodings, but have to be displayed (in 'replace' encoding 
mode)
 > > without breaking the app flow. Thats the pain of the default behaviour
 > > of current python - and there is no simple switch. Why should "print
 > > xy" not print something _always_ as good and as far as possible?
 >
 > Because the author of the application wouldn't know that there
 > is a bug in the application, and that information was silently
 > discarded. Users might only find out much later that they have
 > question marks in places where users originally entered data,
 > and they would have no way of retrieving the original data.
 >
 > If you can accept that data loss: fine, but you should silence
 > the errors explicitly.

this is black/white theoretical - not real and practical (as python 
wants to be). see above.

Robert


More information about the Python-Dev mailing list