読者です 読者をやめる 読者になる 読者になる

methaneのブログ

このブログに乗せているサンプルコードはすべてNYSLです。

file.encoding の convention が判らない

http://docs.python.org/library/stdtypes.html#file.encoding

file.encoding

The encoding that this file uses. When Unicode strings are written to a file, they will be converted to byte strings using this encoding. In addition, when the file is connected to a terminal, the attribute gives the encoding that the terminal is likely to use (that information might be incorrect if the user has misconfigured the terminal). The attribute is read-only and may not be present on all file-like objects. It may also be None, in which case the file uses the system default encoding for converting Unicode strings.

これを見ると、 file.write(unicode_str) すると、 unicode_str は file.encoding に変換されて write されるように見える。だが、Windows で

>>> import sys
>>> sys.stdout.encoding
'cp932'
>>> u = u"あいう"
>>> u
u'\u3042\u3044\u3046'
>>> print >>sys.stdout, u
あいう
>>> sys.stderr.write(u)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-2: ordinal not in range(128)

実際、logging モジュールでも、

                    if (isinstance(msg, unicode) and
                        getattr(stream, 'encoding', None)):
                        #fs = fs.decode(stream.encoding)
                        try:
                            stream.write(fs % msg)
                        except UnicodeEncodeError:
                            #Printing to terminals sometimes fails. For example,
                            #with an encoding of 'cp1251', the above write will
                            #work if written to a stream opened or wrapped by
                            #the codecs module, but fail when writing to a
                            #terminal even when the codepage is set to cp1251.
                            #An extra encoding step seems to be needed.
                            stream.write((fs % msg).encode(stream.encoding))
                    else:
                        ...

のように、file.encoding があるときは file.write(u) してみて、UnicodeEncodeErrorが発生したら file.write(u.encode(file.encoding)) している。

これは、 sys.stdout が file.encoding の convention に従っていないのだろうか?でも、printがencodeしてから出力しているところを見ると、fileにwriteする前にencodeするのは一般的な手続きなのだろうか?

今のところのfile.encodingのconventionは、fileにunicodeを書くときには encoding に変換されるが、変換するのが file.write() の内部なのか file.write() の外で変換してから write()に渡すべきなのかは決まっていない、というものに見える。

キモチワルすぎ。 py3k 早く来い。