pythonスクリプトを2.7.11→3.6.0にしてみた on windows10


自宅スクリプトがpython2.7で動いてるのが懸案事項だったのでpython3にしてみた。
今年の仕事も無事?納まった??ので年越しコーディングがてら。

前提条件:

  • python2.7.11 on windows10
  • IDEはpycharm
  • 対象の既存スクリプトは4つでそれぞれ100行弱くらい、どんな処理あるかは後述

やった流れ

  1. 対象スクリプト洗い出し
    • 普段よく使うスクリプトだけ、今後使わなそうな一時的な検証などでつかったのはもういいかなと
  2. python3.6をwindows上にインストール
    • Download Python | Python.org から3.6.0をDLしてインストール
    • インストールウィザードでPATHの追加のチェックをいれた
    • cmd.exeからの参照したいのも変えたければwindowsの詳細設定から2.7のパスを3.6へ
  3. pycharm設定変更
    • 3.6用のprojectを新規作成
  4. 必要パッケージインストール
    • pycharm上から実施したが、py3になったせいかwindows側の変更が多少必要だた
    • 注意点は後述
  5. 各自コード修正
    • py2用の旧projectから必要スクリプトをそのまま移してエラー箇所を修正&テスト
    • 詳細変更点は後述
  6. 実行パス修正
    • タスクスケジューラやtablacus explorerで参照していたものを変更
    • projectパスも新規projectにしたから変わってるし

どういう処理があってどう対応したか(python2.7.11→py3.6.0)

あくまで「自分の場合は」なので書き方や使う機能でケースバイケースで変更有無変わるし、問題なくは動いたというレベルでpython3としてよい書き方にしたって話ではないです。

各機能 コード変更有無 備考
ファイルの行単位読み出し 変更 a_file.xreadlines→a_file.readlinesへ(後述)
ファイルシステム参照(ls -R的な) そのまま os.pathとos.listdir利用
日本語文字列操作 変更 encoding指定は指定削除(後述)
日本語引数受取 変更 encoding指定は指定削除(後述)
文字列出力 変更 有名なやつ(後述)
文字列置換 変更 encoding指定は指定削除(後述)
文字列整形 そのまま +の文字列連結利用
テキストファイル出力 そのまま codec.open利用
bottle(webサーバ) そのまま bottleを入れ直し
PILで画像サイズ取得 そのまま pillow入れ直したがちょっと手間(後述)
numpyで中央値取得 そのまま numpy入れ直したがちょっと手間(後述)
timeでsleep そのまま
psutilでionice そのまま psutil入れ直し
現在時刻取得 そのまま
osでシステムコマンド実行 そのまま ただ引数授受でエンコーディング変えてたらその指定は不要に
ダイアログ表示(GUI) 変更 ctypesのwin32apiのMessageBoxAを利用(後述)

コード修正など変更詳細

print文

よく見るやつ。

# before
print "hoge"

#after
print("hoge")

文字コードエンコーディング

謎の呪文はもういらない。

# before
import sys
reload(sys)
sys.setdefaultencoding("cp932")

unicode(hoge_string, encoding='cp932')

#after
# 呪文はもういらない! が、書くとしたら上2行は書き方が変わる
import importlib
importlib.reload(sys)
sys.setdefaultencoding('cp932')

# 文字列変数ごとに突っ込んでた指定もいらない
hoge_string

win32api利用でのメッセージボックス表示

MessageBoxAの代わりにMessageBoxWを使う。
参考:Python 3 から MessageBox (Windows API) を呼び出す

# before
def win_alert(mes):
    user32 = windll.user32
    user32.MessageBoxA(
        0,
        mes,
        "info",
        0x00000040)

#after
def win_alert(mes):
    user32 = windll.user32
    user32.MessageBoxW(
        0,
        mes,
        "info",
        0x00000040)

xreadlines

公式ドキュメント見つけられなかったけどxreadlinesはpython3で廃止されたようである。
が、readlinesはあるのでxとった。

# before
for line in itr.xreadlines():

#after
for line in itr.readlines():

参考:2to3を使ってコードをPython 3に移植する - Dive Into Python 3 日本語版

pillowのインストール

まんまwindowsで"pip install pillow"するとインストール時にビルド走ってzlibねぇとか怒られる。
なのであれこれはいってビルド済のバイナリを貰ってきてインストールした。

# ブラウザで以下開いて"Pillow‑3.4.2‑cp36‑cp36m‑win_amd64.whl"をDL
#   http://www.lfd.uci.edu/~gohlke/pythonlibs/
$ pip install Pillow‑3.4.2‑cp36‑cp36m‑win_amd64.whl

参考:Can't install Pillow for Python 3.x in Windows - Zlib is required - Stack Overflow
参考:python - Zlib error when installing Pillow - Stack Overflow
参考:http://www.lfd.uci.edu/~gohlke/pythonlibs/#pillow

numpyのインストール

インストール時のエラーの通り"Visual C++ Build Tools"をいれてから再実行したら入った。

参考:Download the Visual C++ Build Tools (standalone C++ compiler, libraries and tools)

(おまけ)python3のbottleをwindowsのタスクスケジューラから起動するけどコンソールを非表示に

python2の時もbottleのwebサーバをコンソール非表示で自動起動させてた。
が、なんかpythonw.exeでbottleのスクリプトが起動しない...
python.exeで起動すると当然コンソール表示されるし...
(タスクスケジューラの設定バックアップ取り忘れてどう実現してたか謎に...)

で、ぱっと調べたらタスクスケジューラで「ユーザがログオンしているかどうかにかかわらず実行する」を選べば表示されないとか。
できたけど、なんじゃそりゃ。

# タスクスケジューラ上設定
[全般]→[セキュリティオプション]
「ユーザがログオンしているかどうかにかかわらず実行する」

[操作]→[プログラム/スクリプト]
"C:\hoge\Python36\python.exe"

[操作]→[引数の追加]
C:/hoge/bottle_sample.py


参考:Windows7でタスクスケジューラから実行するバッチファイルが画面に表示されません。 - マイクロソフト コミュニティ

おわりに

対象が小規模で簡素な機能ばかりだったからか、調べながらでも全体で1,2時間でできたので割りと簡単に動くなと。
ただpython3として正しい書き方か?は全然意識してないのでちゃんとそこはおいおい勉強していかないと...

特にwindowsで日本語で辛い思いをしてた人にはやはりpython3へのバージョンアップは必須だなとじみじみ。
(もうcp932とか謎文字コード使ったり、encodingとdecodingとunicode()の整合性一致を気にしなくていい)

だいたいライブラリがもう対応してきてるし。
(これでrubyとかphpみたいにn倍早くなるとかあればゲフンゲフン)

以上。