高知からリモートインターンしている森田ドラゴンです。昨日のインターンでは3時間ほどしか作業できなかったので、今日まとめて記事を書きます。やっていたことは、pythonのテストコードを書きながらのdebugです。テストコードを書くことよりも、pythonのdebugに結構ハマりました。
ハマったこと
pytest ,ファイルがimportできない
とりあえずpytestが動かないと話にならないので、pytestを実行してみたものの、moduleが存在しないよ〜、とエラーが。
ModuleNotFoundError: No module named 'app'
app.pyというメインファイルは存在しているし、実験的に作った他のファイルでのテストと同じコードを書いているはずなのに、なぜか動きませんでした。
調べていくと、下記のコードを書き込んで、モジュールとして認識させる必要があるみたいです。他のファイルで試した時は、下記の処理を書いていないので、なぜ通ったのかは謎です。これをする必要はないと思うので、また調べる時間を作って勉強します。
import sys
sys.path.append('/課題/weather-api') #フルパス
loggerを動かしたい
pytestは実行できるようになったものの、エラーが発生した場合に、元のページのコードが見える処理を書いていないので、logを出力する必要がありました。loggerをimportすれば動かせそうだったんですが、ファイルに出力する設定を書かないといけないみたいです。
今後、aws リソースとpythonをテストしていくことを考えると、logファイルを作ったほうが良さそうでしたが、今回の場合はコンソール場で表示したいだけだったので、色々と試していました。テストの度に cat test.logと打ち込むのは面倒ですし、logが積み重なっていくと見づらくなることを嫌ったからです。
悔しいことにできなかったので、ファイルに出力するやり方でlogを確認することにしました。(こちらは記事がたくさんありました)
logging.basicConfig(filename='test.log', level=logging.DEBUG)
logger = logging.getLogger("output")
APIレスポンスの形式はbyte型
debugを始めて最初につまったのが、livedoor お天気apiからのレスポンスの形式です。前調べではjsonファイルが返ってくると公式サイトに書かれていたのですが、実際に返ってきたデータはbytes型で、jsonとして利用できずデータが取り出せませんでした。
最初はレスポンスの型が原因だとは思わなかったので、気づくまでに時間がかかりました。bytesからjsonに変換するコードは以下になります。一度、str型にしてあげる必要があるようです。
json_data = json.loads(body.decode()) # decode()で bytes -> strの変換
urllibのエラーをキャッチする
森さんからプログラムの正常ルート、エラールートについて教えていただいたので、try catchで例外処理を追加しました。詰まったのは importした urllib ライブラリで出力された、エラーを検知する方法です。
logを確認すると、エラー自体はレスポンスとして返しているようなので、「レスポンスをエラーとしてキャッチするにはどうすればいいか?」という切り口で考えていました。実はそんなことしなくても logに出ていたエラーコードを貼り付けるだけでよかったんですけどね。
try:
with urllib.request.urlopen(req) as res:
body = res.read()
except urllib.error.HTTPError as e:
print(e)
return "E002"
except Exception as e:
print(e)
return "E000"
例外処理は始めると切りがなさそうだったので、予想できないエラーが起きた場合の処理も追加しました。ちなみにリターンで返しているE002というのはエラーコードです。ただ、エラーコードと正当なコードを同じレスポンスとして返すのは、なんだかなあという感じがします。API GWの設定で、404エラー等を返せるようにしたいです。
感想
やっとまともにデバッグができるようになったので、pythonコードを(おそらく)完成させることができました。次はAPI GWをSAMでデプロイすることです。問題は、
・POSTのデータマッピングをどう設定するか
・Swaggerを読み込ませるコードを書く
Swaggerは単純に仕様書の役目かと思っていたら、SAMでは記述しきれない細かな設定を定義できる、テンプレートの役割も担っているようです。こちらはimportすればできそうです。
POST形式のAWS SAMの設定の仕方が調べても出てこなくて、API のサンプルを調べてみようかなと思ってます。