みんなのPython を3.xで勉強するためのTips

みんなのPython Webアプリ編がPDFで無料公開されていますが、この本はPython 2.x向けに書かれているので、3.xではそのまま動かない点がチラホラ・・・

とりあえずChapter04を読んでみたところ、以下のような変更が必要です。

CGIHTTPServer -> http.server

3.xでは、標準ライブラリが整理され、名前が変わっている場合があります。

#2.x
import CGIHTTPServer
CGIHTTPServer.test()

#3.x
import http.server
http.server.test(HandlerClass=http.server.CGIHTTPRequestHandler)

文字列リテラル

3.xではコーテーションで囲ったものが、2.xでいう文字列を表すようになりました。

#2.x
greeting_string = u"Hello 世界"

#3.x
greeting_string = "Hello 世界"

なお、ファイルの2行め(エンコーディング指定の次の行に)に、from __future__ import unicode_literals追加すると、2.xでも3.xと同じ扱いになります。

#encoding: shift-jis
from __future__ import unicode_literals

greeting_string = "Hello 世界"

また, 2.xでにおけるunicode関数は, 3.xではstrという名前になっています。

print文 -> print関数

#2.x
print something

#3.x
print(something)

バイト列を出力 -> 文字列を出力し、自動変換

一番クリティカルな変更です。

2.xのprint文は、バイト列(2.xのstr)を受け取るのが基本で、unicodeは明示的にバイト列に変換することになります。

一方、3.xのprint関数はユニコード文字列(3.xのstr)を受け取るのが基本で、2.xのつもりでバイト列を渡しても期待した動作にはなりません。

#2.x
print(u"あ".encode("cp932")) #-> あ

#3.x
print("あ".encode("cp932")) #-> b'\x82\xa0'

2.xでは .encode("utf-8").encode("shift-jis")などとすることで、出力するHTMLのエンコーディングを変更出来たのですが、
3.xではこのテクニックは使えず、出力のエンコーディングはsys.stdout.encodingに固定です。

では、3.xではどうすれば良いかというと、sys.stdoutの値自体を変えてしまえば良いのです。

#3.x
import sys
import io
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')

print("あ") #自動でutf-8エンコードされて出力される

元に戻すには、sys.__stdout__に本来のsys.stdoutが保存されているので、これを再代入します。

#3.x
import sys
sys.stdout = sys.__stdout__