前回の記事でコアサーバで Python CGI は簡単に動くことがわかりましたが、外部ライブラリを使用したところエラーが出るようになりました。
ちょっと苦戦しましたが、なんとか動いたので原因と対策を書いておきます。
外部ライブラリの使用でエラーが発生?
まずは参考にしているページです。
2019年12月の記事ですが、このページではコアサーバーで3つの Python CGI を試してます。
この記事の「Hello World 表示サンプル」「入力値の表示サンプル」までは順調に実施できたのですが、「外部ライブラリ利用サンプル」を行ったところ「Internal Server Error」が表示されました。
まずは実際に実施した内容を記載しておきます。
元記事では ~/my-space に numpy、matplotlib パッケージのインストールをしてますが、python のバージョンが 2 と 3 共存しているので、とりあえずバージョン3のパッケージという意味で、~/my_py3 というディレクトリにしました。
(ちなみに自分も Python はちょっと触ったことがある程度の初心者です。笑)
draw.py のソースも元記事のものから日本語コメント無しにしたものを載せておきます。
また、元記事とはフォルダ構成が違うのでライブラリ読込パスを「../../../my_py3」としてます。
そして、https://teqnobreaker.com/work/draw.py にアクセスしてみたところ以下のエラーとなりました。
エラー原因の調査
「Internal Server Error」で表示されてるメッセージを見ると「コアサーバーの管理者に聞いてね」とのことか。
ちなみに error log に情報が出ているとあり、通常、webサーバー(apache)の error_log は /var/log/httpd/error_log、もしくは「/etc/httpd/conf/httpd.conf」で出力箇所を指定するようです。
しかし、/var/log、/etc 配下は「Permission denied」でアクセス権が無いので見れません。
ソースを見て原因になると思われるものを考えて潰して行きます。
① ライブラリの読込に失敗している「../../../my_py3」
もしかすると、public_html/teqnobreaker.com/ 配下じゃないと参照できないとか?
② そもそも外部ライブラリを許してない
これはそんな制御ができるのかは不明。
③ ライブラリは読み込めているが画像の出力に失敗している
ライブラリが古いとかは無いだろうか。
まずは①を確認しようと、~/my_py3 を public_html/teqnobreaker.com/work 配下に移動して動かしたけど「Internal Server Error」で変わらず。
あ、もしかするとライブラリが python 2 用になってたりするのかも?
そもそも、コアサーバーでライブラリのインストールはできるもんなんだろうか?
検索すると、以下の記事を発見。
あまり詳しくは書いて無いが他のページなども見た結果、以下がわかった。
・pip が古い場合があるので最初に pip のアップグレードをする
・--user を付けると自分のホームディレクトリの .local 配下にライブラリはインストールされる
・.local 配下だとライブラリのパスが通ってるのでソースでパスを追加する必要は無し
前回ライブラリをインストールした時のログをよく見ると、しっかり以下の警告が出てるでは無いか。
ということで、pip のアップデートをして numpy、matplotlib をインストールした。
この後、ライブラリのパスの指定無しで実行するも「Internal Server Error」のまま。
うーん、そもそもライブラリの読込で失敗してたりするのだろうか。
確認するために新しいライブラリを読み込むだけで「Hello, World!」を表示するソースを「draw1.py」として作ってみた。
これなら動くだろうと、https://teqnobreaker.com/work/draw1.py を実施してみるが、まさかの「Internal Server Error」。
ということは、ライブラリ読み込みがダメってことなのか!?
そうか、試しにコマンドラインで実行したらエラーがわかるかも。
え!?エラーにならない!?
python を直接動かすとエラーにならないのに、httpアクセスでCGIとして動かすとエラーになるということは、httpアクセスの場合のユーザが違うから .local のパスを見てないということか?
python のライブラリパスは sys.path に入ってるそうなので、これを表示すればコマンド起動時とhttpアクセス時のライブラリパスの違いがわかりそう。
ということで sys.path を表示するプログラム「sys_path.py」を作ってみた。
まずはこれをコマンドで起動してみる。
なるほど途中に「'/virtual/cuzuser/.local/lib/python3.6/site-packages'」が入ってる。
今度はhttpで起動。
あれ!?ちゃんと「'/virtual/cuzuser/.local/lib/python3.6/site-packages'」が入ってる!?
これは、、煮詰まりました。。
正解は?
いろいろ検索してなかなかわからなかったのですが、以下の記事を見てわかりました。
簡単に言うと、処理が重いCGIは応答時間が遅いのでwebサーバーが「Internal Server Error」にしてしまうようでした。
この記事では解決策として、php経由でxxx.pyを実行する方法が記載されています。
phpの場合は処理が多少遅くてもエラーにならないということですね。
このページにあるサンプルの test.py、test.php などを作って確かめてみると、確かに test.py はhttp起動ではエラーになるけど、test.php経由だと表示されました。
ただ、このサンプルでは test.py の出力結果を test.php で表示するというものなので、draw.py の場合のバイナリ出力を php 側でもらって画像として出すというのを作ろうと試みましたが、自分の技術では上手く作れなかったです。
元のやり方と違うのでイマイチではありますが、draw2.py で img.png というファイルを出力するようにして、draw2.php で img.png を表示するようにすることで動かすことはできました。
とりあえず外部ライブラリが動くことを確認できたので良しとしよう。笑
画像ではdraw1.phpになってますが文に合わせてdraw2.php にしてます。たしかに表示が遅いです。
https://teqnobreaker.com/work/draw2.php
コメント