h05torです。
プログラミング関係の備忘録記事です。
業務で使ってるアプリをweb化するためpythonanywhereというサービスを利用しています。
前にも一度記事で触れましたが、私はFlaskというwebフレームワークでwebページを作っております。
まずは、ローカル環境でテストして、それをpythonanywhereに移植するという流れになるのですが、ローカルでは問題なく動くのにpythonanywhereだとなぜかエラーになることがよく起こります。
具体的にはモジュールのバージョンがPCに入っているものと異なるというものだったり、入力欄に入れた数値をJavascriptでAjaxを用いてサーバー側(Python)に渡すしたものがPCだと浮動小数点型と認識されていたのに、pythonanywhereだと何故か文字列になってたりして途中の計算式で止まるというケースがありました。
普通にPC内でspyderとかの開発環境やAnacondaプロンプトみたいなのでプログラムがミスってた場合だと以下のようにどこ(何行目)で何が(NameErrorとか)ミスってたのかというのが一目瞭然で分かります。
Traceback (most recent call last): File "Main.py", line 4, in <module> print(x) NameError: name 'x' is not defined
しかし、pythonanywhere上で走らせた場合だと、メインのpyファイル(flask_app.py)の場合はエラーログに記録されるため問題ないのですが、関数を別もモジュールファイルに書いている場合だと、エラーログに残らずに、どこでエラーが起きているのか分からなくなります。
↓一応エラーログはあります。
そこで、私は例外処理(try~ except~)を置いて、例外が発生した場合のexceptの中にcsvファイルを出力させるコードを入れて、そのcsvの中にエラーの内容と行数が出力されるようにしております。
import sys
import csv
try: vis = int(databox["viscosity"]) * (10**-3) Pnet = databox["Np"] * 1000*databox["pl"] * ((Nm/60)**3) * ((databox["di"] * 10**-3)**5) / 1000 Pcal = Pnet / (databox["η"] * 0.85) except: with open('error4.csv', 'w') as f: writer = csv.writer(f) writer.writerow(sys.exc_info()) writer.writerow(str(sys.exc_info()[-1].tb_lineno))
tryの中で例外が発生するとexceptに飛び、その中でwith open......って感じでcsvファイルを出力しております。
ここで、sys.exe_info()で、どのようなエラーが発生したかを出力します。
続いて、sys.exc_info()[-1].tb_linenoでエラーが発生した行数が表示されます。
sys.exc_info()[-1]ってあるのでsys.exe_info()の最後尾に入ってるんじゃないの?と思うかもしれませんが、csv開いてみると例えば
<class 'UnboundLocalError'>,local variable 'Nm' referenced before assignment,<traceback object at 0x7f007bf52980>
のように行数を表しているはずの最後尾の要素が<traceback object at 0x7f007bf52980>となっていて行数が表示されていないのです。
そこでsys.exc_info()[-1].tb_linenoとすることで、内容が解凍?され、行数が出力されるようになるという仕組みです。
これ調べるのにちょいっと時間かかったので、備忘録として記事に残しておきます。