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

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

前提条件:

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


# やった流れ

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

```py3
# before
print "hoge"

#after
print("hoge")
```

## 文字コードエンコーディング
謎の呪文はもういらない。

```py3
# 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) を呼び出す](https://wq1.github.io/blog/2014-10-30/)

```py3
# 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とった。

```py3
# before
for line in itr.xreadlines():

#after
for line in itr.readlines():

```
参考:[2to3を使ってコードをPython 3に移植する - Dive Into Python 3 日本語版](http://diveintopython3-ja.rdy.jp/porting-code-to-python-3-with-2to3.html)


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

```bash
# ブラウザで以下開いて"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](http://stackoverflow.com/questions/38733647/cant-install-pillow-for-python-3-x-in-windows-zlib-is-required)
参考:[python - Zlib error when installing Pillow - Stack Overflow](http://stackoverflow.com/questions/39196258/zlib-error-when-installing-pillow)
参考: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)](http://landinghub.visualstudio.com/visual-cpp-build-tools)

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

で、ぱっと調べたらタスクスケジューラで「ユーザがログオンしているかどうかにかかわらず実行する」を選べば表示されないとか。
できたけど、なんじゃそりゃ。
![タスクスケジューラ.png](https://qiita-image-store.s3.amazonaws.com/0/26677/9917f7c1-2690-e1b0-defd-680a45be47e0.png)

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

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

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


```

参考:[Windows7でタスクスケジューラから実行するバッチファイルが画面に表示されません。 - マイクロソフト コミュニティ](https://answers.microsoft.com/ja-jp/windows/forum/windows_7-winapps/windows7%E3%81%A7%E3%82%BF%E3%82%B9%E3%82%AF/ccff2c2f-5a0e-4f3d-ae81-9dff3e36fc3c)

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

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

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

以上。