プログラミング素人のはてなブログ

プログラミングも電気回路も専門外の技術屋の末端が勉強したことや作品をアウトプットするブログ。コードに間違いなど見つけられたら、気軽にコメントください。 C#、Python3、ラズパイなど。

Flaskで学ぶPythonのErrorの読みかた

Errorを読めない人は読んでないだけ

Errorの内容って読めない人はいつまでも読めないんですよね。
togetter.com

一方で、Errorの読み方というのを上手く説明しているWebも見つからなくて最初は私も苦労しました。
そこで、最近必要あってPythonのFlaskというWebサーバーのモジュールを初めて使ってみたので、この機会にどのようなErrorメッセージがどのように出るかを確認しながら、その解読方法をまとめてみました。
意外と漫然と見ているとスタックトレースが、親プロセスからさきに出てくるのか子プロセスからさきに出てくるのかとか分からないものです。

Errorメッセージと対処方法

まず適当なコードを書いて、初めて起動しようとしたとき以下のようにErrorメッセージが出ます。(環境によって異なります。)

xxx@raspberrypi:~/flask $ python3 main.py
Traceback (most recent call last):
  File "main.py", line 5, in <module>
    from flask import Flask, render_template, make_response, send_file, send_from_directory
ModuleNotFoundError: No module named 'flask'

Error出力の基本構文は、
File <ファイル名>line <何行目>in <Errorの起きた構文>です。
ここではfrom flask import Flask, ~の行に対してErrorが発生していて、最後にかかれているように、flaskというモジュールが見つからないことが原因です。つまり、Pythonの「flask」がインストールされていないので

$ pip3 install Flask

のようにインストールを行います。
インストールするpip~はモジュールが分かればググるとインストール方法が分かるはずです。
python flask」などでググります。

次は↓のようなErrorが出ます。

xxxx@raspberrypi:~/flask $ python3 main.py
Traceback (most recent call last):
  File "main.py", line 8, in <module>
    from matplotlib.backends.backend_agg import FigureCanvasAgg
ModuleNotFoundError: No module named 'matplotlib'

今度はPythonのmatplotlibがインストールされていないというErrorです。

$ sudo apt-get install python-matplotlib

のようにインストールします。

次はやっとFlaskが起動しようとしました。

* Serving Flask app "main" (lazy loading)
* Environment: production
WARNING: Do not use the development server in a production environment.
Use a production WSGI server instead.
* Debug mode: on
Traceback (most recent call last):
File "/home/***/Flask/main.py", line 86, in <module>
app.run(debug=True, host='0.0.00', port=8888, threaded=True)
File "/usr/lib/python3/dist-packages/flask/app.py", line 943, in run
run_simple(host, port, self, **options)
File "/usr/lib/python3/dist-packages/werkzeug/serving.py", line 795, in run_simple
s.bind(get_sockaddr(hostname, port, address_family))
socket.gaierror: [Errno -2] Name or service not known

まず、以下の部分はFlaskを起動しようとしているLogで、Errorではありません。
ただの英語ですが、プロダクション環境で起動しようとしているけど、開発サーバーをプロダクション環境で使わないほうがいいよ、代わりに本番用のWSGIサーバーを使用してください。デバッグモードです、というようなことを言っています。

* Serving Flask app "main" (lazy loading)
* Environment: production
WARNING: Do not use the development server in a production environment.
Use a production WSGI server instead.
* Debug mode: on

Traceback からがErrorの内容です。
ここでは3つのErrorが芋づる式に出ています。
Tracebackとは記録を遡ること、つまりErrorが出た原因を遡って出力しています。
基本的には呼び出した順番に上から出力されているはずです。

File "/home/**/Flask/main.py", line 86, in <module>
app.run(debug=True, host='0.0.00', port=8888, threaded=True)

つまりmain.pyの 86行目、app.run.... のところで最初のErrorが発生しました。

次に、↑の最初のap.run.....は flaskのapp.py ↓ を呼び出しています。

File "/usr/lib/python3/dist-packages/flask/app.py", line 943, in run
run_simple(host, port, self, **options)

↑のapp.pyは serving.py ↓ を呼び出しています。

File "/usr/lib/python3/dist-packages/werkzeug/serving.py", line 795, in run_simple
s.bind(get_sockaddr(hostname, port, address_family))

最後に出力されているのがきっかけとなった↓のErrorです。
serving.py のなかにあるもので、詳細はわからないですが↓のErrorが発生し止まったということになります。

socket.gaierror: [Errno -2] Name or service not known

なので、まずは自身が記述したmain.pyの86行目に問題がないか確認します。
構文エラー、タイプミス、引数の使い方など。
これで原因がつかめなければ次のエラー(flaskのapp.py)のエラーを見ます。
run_simple(host, port, self, **options)とあるので、ここに渡している引数がおかしい可能性があります。
ここでは、1つめのapp.run()の引数と2つめ
run_simple()の引数が似ていつことから、このあたりに問題があると考えられます。
このように考えても原因がわからない場合は、さらに3つめを見て、3つめのエラーをググります。
または、ライブラリがversion不一致とか、他のライブラリと干渉しているなどを疑います。

ここでは、app.run(debug=True, host='0.0.00', port=8888, threaded=True)の0.0.0.0がタイプミスでした。

サーバーが起動したら、今度は以下のようなErrorがでました。

xxx@raspberrypi:~/flask $ sudo python3 main.py
Traceback (most recent call last):
  File "main.py", line 19, in <module>
    fig = plt.figure()
  File "/usr/lib/python3/dist-packages/matplotlib/pyplot.py", line 535, in figure
    **kwargs)
  File "/usr/lib/python3/dist-packages/matplotlib/backends/backend_tkagg.py", line 81, in new_figure_manager
    return new_figure_manager_given_figure(num, figure)
  File "/usr/lib/python3/dist-packages/matplotlib/backends/backend_tkagg.py", line 89, in new_figure_manager_given_figure
    window = Tk.Tk()
  File "/usr/lib/python3.5/tkinter/__init__.py", line 1880, in __init__
    self.tk = _tkinter.create(screenName, baseName, className, interactive, wantobjects, useTk, sync, use)
_tkinter.TclError: no display name and no $DISPLAY environment variable

今度はfig = plt.figure()でErrorが出ています。
続けて呼び出されているのはmatplotlibtkinterの中身のようです。
しかし、matplotlibは使っているのですが、tkinterは使っていません。
なぜ呼び出されているのでしょう?
ここでは、fig = plt.figure()にはタイプミスがなさそうです。

このように自分の書いたコードに問題が見つからないときは、最後の出力をググります。
ヒットしなければ、「ラズパイ」などのキーワードを追加します。

ラズパイ matplotlib “_tkinter.TclError: no display name and no $DISPLAY environment variable”

↓のような記事が見つかりました。
nc30mtd.oops.jp

まとめ

PythonのErrorの読み方を解説しました。
基本は、最初の出力か最後の出力に解決策が見つかることが多です。
これでわからないときは最後の出力をググります。
必要に応じて「ラズパイ」「Windows」「Python」などのキーワードを付加すると見つかることが多いです。
これでも見つからない場合は「RaspberryPi」などの付加キーワードで英語のページを探します。
これでもこれでも見つからないときは、公式GitHubのIsssueを探します。