AWS Lambda Python2 を Python3 に変換した記録

わかっちゃいたけど後回しにしていた Lambda Python2、たまたまやる気が燃え上がったので Python3 に移行しました。

Python 自体はまぁそこそこの素人なので、詳しいことはあんま書かないで、やったこととか変更点のピックアップとかしていきたいと思います。



Python2 よや すら かに

Python2 がこんな感じで終焉を迎えるので、

Lambdaの公式説明的には、段階的ではあるものの、End of life 以降は使えなくなっていくので、それまでに切り替えようねということになります。

Pythonの公式をチェックすると、Python2.7 は 2020-01-01 なので、もーさすがに頃合いというか早よやれって感じですね。

Lambda Python2.7 が 2015年10月にリリースされ、

Lambda Python3.6 が 2017年4月、

Lambda Python3.7 が 2018年11月、

で、ウチのLambdaさんは Python2.7 しかない時代から開発し始めたのと、インフラ用のコードはそうたいした内容ではないので、そのまま 2.7 で動かしてきたのですが、12月にこんなことやりたくないので、マル済にしておいた次第です。

ここからは作業内容についてまとめていきます。


Gitの作業

インフラ用のLambdaコードは、Git で管理していて、master に merge したら CI が zip にして S3 にアップロードしてくれる、ようにしています。zip はメインコードと、ライブラリなどのレイヤーに分けることで、更新時の無駄な転送などを減らしています。

その構成をそのままに、Python3 用に新しくレポジトリを作成して、コードを丸っとコピーして、CI関連の設定もコピー&編集して準備完了です。


開発環境での作業

Python3 の準備

私は CentOS7 で作業していたので、python3 の準備から始まります。

python3-devel は mysqlclient のコンパイルと、2to3 コマンドで必要になります。

Version は Python3.6 になります。Runtime EOL 的に、3.7 にしてしまおうとも思ったのですが、CentOS8 ですらまだ標準が 3.6 なので、pyenv とかあっち系を運用手順にあまり入れたくないし、まだ2年あるしいいかなって感じです。非常に微妙なラインなので、管理者の決断任せで大丈夫だと思います。

pip3 でパッケージインストール

Lambda に色々持っていくやつを、コードに含めてしまいます。今回、MySQL-Python が Python2 で動かなくなっているので、その Fork である mysqlclient に切り替えています。

この python/ ディレクトリは、レイヤーとして外だししています。

あと余談ですが、手元の 3.6 でインストールしたものを、lambda python 3.7 で動かそうとしたらダメでした。

libmysqlclient のコピー

mysqlclient で必要になるので、不格好ですが持っていきます。

lib/ はコードのどこかで扱えるようにしています。


2to3-3 コマンドでコード変換

2to3-3 で .py を指定すると、変換の diff を確認できます。オプションで -w をつけると、実際に変換して、かつ元のファイル名 + .bak でオリジナルを保管してくれます。

どーでもいいですけど、2to3 ってだいぶ傲慢な名付けですよね…… せめて py2to3 とかにすればいいのに:-(


diff ピックアップ

python2 と 3 の違いは、ググってもらうとして、ウチの場合はこんな変更点が出ましたよという、例でも出しておきます。ぶっちゃけ、たいしたことなかったです:-)

print

基本案件です。


list ラップ

主に for での変数の扱いにおいて、list() で囲む必要があります。


not in

has_key よりは not in の方が簡単だし好みではある。


文字列の型

これは自動変換してくれましたが、してくれない系もあってあとで手こずります。


8進数

書き方が変わりました。


lambdaいらず

この filter よりは for in の方が綺麗ですね。っていうか、こんな変換してくれるのは凄い。


urllib

そうなりましたか、くらい。


引っかかったところ

2to3 のあとに一通り動作確認をしていって、残ったエラーを修復していきます。

MySQL-Python -> mysqlclient

さきほども書きましたが、pip3 install の時点で MySQL-Python のインスコで、こんなエラーが出て失敗します。
  • ModuleNotFoundError: No module named ‘ConfigParser’

  • これを mysqlclient に変更することで、コードの変更はゼロで対応完了となります。

    文字列の str と bytes

    文字列型の扱いが変わったことで、変換を求められます。

    例えば、struct でこんなエラーが出たので、引数の文字列に b をつけたり、結合時に型を合わせるために変換したり、
  • argument for ‘s’ must be a bytes object

  • POSTデータを bytes に変換するなど。

  • POST data should be bytes, an iterable of bytes, or a file object. It cannot be of type str.

  • さすがに処理に使う変数の型は、自動変換で見えるはずがないので、struct や sock など bytes での取り扱いになった系を把握して、片っ端から対応していくことになります。



    と、まぁ思ったよりスンナリ終わったので拍子抜けしました。インフラ用コードがたかが知れてるってのもありますけど。

    Lambda の Python を書いている時は、とても心が安らぐので、また数年お世話になって、また数年後に更新するくらいは、気持ちよくやっていきたいと思いマッスル!!