Nginx + uWSGI で「おもしろまじめなAIスピーカーアプリをつくろう」(秀和システム)のサンプルプログラムを動かす
先日お父ちゃんの依頼でサーバでPythonを動かせるようにしたのだけど、
こちらの本のサンプルプログラムを動かそうとしたところ 再び Internal Server Error になってしまった。
Python 自体よく知らないので何がなんだかという感じで google 検索に頼りつつ、なんとか動かせるようになったので記録…
元のソースコードを
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
#!/usr/local/bin/python2.7 # -*- coding: utf-8 -*- import json import sys input = json.load(sys.stdin) print("Content-type: application/json\n\n") output = { "speech": "Hello." # "speech": u"こんにちは。" } json.dump(output, sys.stdout) |
uWSGI用にするため下記の変更を加えた。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
#!/usr/lib/python2.7 # -*- coding: utf-8 -*- import json import sys #input = json.load(sys.stdin) print("Content-type: application/json\n\n") output = { "speech": "Hello." # "speech": u"こんにちは。" } data = json.dumps(output) def application(env, start_response): start_response('200 OK', [('Content-Type','text/html')]) return data |
目次
変更点のメモ
1行目 – #!/usr/lib/python2.7
1 2 3 |
#!/usr/local/bin/python2.7 ↓ #!/usr/bin/env python |
まず、自分のpythonの場所を調べるのに下記ページを参考にさせて頂き、
Pythonのインストールパス確認 – PGとして困ったとき用のメモ書き
1 2 3 4 5 6 7 |
$ python Python 2.7.9 (default, Sep 17 2016, 20:26:04) [GCC 4.9.2] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> import sys >>> sys.path ['', '/usr/lib/python2.7', '/usr/lib/python2.7/plat-arm-linux-gnueabihf', '/usr/lib/python2.7/lib-tk', '/usr/lib/python2.7/lib-old', '/usr/lib/python2.7/lib-dynload', '/usr/local/lib/python2.7/dist-packages', '/usr/lib/python2.7/dist-packages', '/usr/lib/python2.7/dist-packages/gtk-2.0', '/usr/lib/pymodules/python2.7'] |
/usr/lib/python2.7 であることがわかった。
ただ、色々なソースコードを見ていると「#!/usr/bin/env python」と指定されてあるものがあったので何故なのかと調べてみたところ、
「#!/usr/bin/python」と「#!/usr/bin/env python」の違い – 座敷牢日誌
「#!/usr/bin/python」とした場合は、フルパスで指定されているpythonインタプリタを使って実行する。「#!/usr/bin/env python」では環境変数 PATHのなかに含まれているpythonを探して実行する、ということだ。
とのことだった。
#!/usr/bin/env python とした方がバージョンが変わった際に最新バージョンを使用出来るメリットがあるのかな? でも探す、という処理が含まれてしまうから「/usr/lib/python2.7」を指定した方が少し軽くなるのかな。
サンプルプログラムと同じ形式で「/usr/lib/python2.7」を指定しておいた。
7行目 – input = json.load(sys.stdin) をコメントアウト
結局原因がわからなかったのだけど、sys.stdin でエラーが出るようだった。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
*** Operational MODE: single process *** Traceback (most recent call last): File "/PATH/hello.py", line 7, in <module> input = json.load(sys.stdin) File "/usr/lib/python2.7/json/__init__.py", line 290, in load **kw) File "/usr/lib/python2.7/json/__init__.py", line 338, in loads return _default_decoder.decode(s) File "/usr/lib/python2.7/json/decoder.py", line 366, in decode obj, end = self.raw_decode(s, idx=_w(s, 0).end()) File "/usr/lib/python2.7/json/decoder.py", line 384, in raw_decode raise ValueError("No JSON object could be decoded") ValueError: No JSON object could be decoded unable to load app 0 (mountpoint='') (callable not found or import error) |
調べてみたけどよくわからなかった・・・
同じような質問が見つかったけど解決してないようだったし…
json – Python CGI script hangs with uWSGI trying to read sys.stdin – Stack Overflow
jsonをパースするために必要なようなので、違う方法で実装すれば良いんじゃないかと思い、コメントアウトした。
16行目 – data = json.dumps(output)
dump を dumps に変更
8行目をコメントアウトして sys.stdout が使えなくなったのでこちらも変更する必要が生じた。
最初、sys.stdout を除いただけの json.dump(output) で試したらエラーが出てしまった。
1 2 3 |
File "/var/share/www/hmg/uwsgi/hello.py", line 18, in main json.dump(output) TypeError: dump() takes at least 2 arguments (1 given) |
調べたら所、dump を dumps にすれば良いっぽかった。
Python – dump dict as a json string – Stack Overflow
dump と dumps は何が違うのか調べてみた。
[Python] JSONを扱う – YoheiM .NET
- dumps関数:PythonオブジェクトをJSON文字列に変換する
- dump関数:PythonオブジェクトをJSON形式でファイルに書き込む
ついでに dump の方でファイル書き込みも試してみたら出来た。
1 2 |
f = open("output.json", "w") json.dump(dict, f) |
ファイルは事前に作成しておかないとエラーが出た。
1 2 3 4 5 6 |
Traceback (most recent call last): File "/PATH/hello.py", line 21, in application main() File "/PATH/hello.py", line 17, in main f = open('output.json', 'w') IOError: [Errno 13] Permission denied: 'output.json' |
変数に格納
def application の return に渡すため変数に入れた。
18-20行目 – def application(env, start_response):
ここもよく理解は出来ていないのだけど、WSGIアプリケーションのインターフェース に渡すために、def application を使用する必要があるという感じぽい…????
第1回 WSGIの概要:WSGIとPythonでスマートなWebアプリケーション開発を|gihyo.jp … 技術評論社
とりあえずこれで無事ブラウザに「{“speech”: “Hello.”}」が表示された!????