【レンタルサーバー】コアサーバーで Python CGI を動かしてみる(後編)

レンタルサーバー
記事内に自動で広告が表示されます

前回の記事でコアサーバPython CGI は簡単に動くことがわかりましたが、外部ライブラリを使用したところ「Internal Server Error」が出るようになりました。

ちょっと苦戦しましたがなんとか動いたので、原因と対策や実施した手順やコマンドなどを記載しておきます。

【レンタルサーバー】コアサーバで Python CGI を動かしてみる(前編)
コアサーバにログインできることがわかったので、Python CGI を試してみました。 最初は順調でしたが、ちょっと苦戦してなんとか動くようになりました。実施した手順やコマンドなどを記載しておきます。本記事ではエラーが発生したところまでを記載してます。

外部ライブラリの使用でエラーが発生?

まずは参考にしているページです。
2019年12月の記事ですが、このページではコアサーバーで3つの Python CGI を試してます。

CORESERVER で Python の CGI を動かす - Qiita
概要GMOデジロックのレンタルサーバー「コアサーバー」で Python の CGI を動作させる今回...続きを読む

この記事の「Hello World 表示サンプル」「入力値の表示サンプル」までは順調に実施できたのですが、「外部ライブラリ利用サンプル」を行ったところ「Internal Server Error」が表示されました。

まずは実際に実施した内容を記載しておきます。

元記事では ~/my-spacenumpymatplotlib パッケージのインストールをしてますが、python のバージョンが 2 と 3 共存しているので、とりあえずバージョン3のパッケージという意味で、~/my_py3 というディレクトリにしました。
(ちなみに自分も Python はちょっと触ったことがある程度の初心者です。笑)

Bash
[cuzuser@xxxx ~]$ python3 -m pip install numpy matplotlib --target ~/my_py3
Collecting numpy
  Downloading https://files.pythonhosted.org/packages/14/32/d3fa649ad7ec0b82737b92fefd3c4dd376b0bb23730715124569f38f3a08/numpy-1.19.5-cp36-cp36m-manylinux2010_x86_64.whl (14.8MB)
     |################################| 14.8MB 12.8MB/s
Collecting matplotlib
  Downloading https://files.pythonhosted.org/packages/d2/43/2bd63467490036697e7be71444fafc7b236923d614d4521979a200c6b559/matplotlib-3.3.3-cp36-cp36m-manylinux1_x86_64.whl (11.6MB)
     |################################| 11.6MB 47.2MB/s
Collecting pyparsing!=2.0.4,!=2.1.2,!=2.1.6,>=2.0.3 (from matplotlib)
  Downloading https://files.pythonhosted.org/packages/8a/bb/488841f56197b13700afd5658fc279a2025a39e22449b7cf29864669b15d/pyparsing-2.4.7-py2.py3-none-any.whl (67kB)
     |################################| 71kB 23.9MB/s
Collecting pillow>=6.2.0 (from matplotlib)
  Downloading https://files.pythonhosted.org/packages/b6/c0/442d9d87e0da00bf856ef6dd4916f84a2d710b5f1a367d42d7f3c4e99a6c/Pillow-8.1.0-cp36-cp36m-manylinux1_x86_64.whl (2.2MB)
     |################################| 2.2MB 26.8MB/s
Collecting kiwisolver>=1.0.1 (from matplotlib)
  Downloading https://files.pythonhosted.org/packages/a7/1b/cbd8ae738719b5f41592a12057ef5442e2ed5f5cb5451f8fc7e9f8875a1a/kiwisolver-1.3.1-cp36-cp36m-manylinux1_x86_64.whl (1.1MB)
     |################################| 1.1MB 40.4MB/s
Collecting python-dateutil>=2.1 (from matplotlib)
  Downloading https://files.pythonhosted.org/packages/d4/70/d60450c3dd48ef87586924207ae8907090de0b306af2bce5d134d78615cb/python_dateutil-2.8.1-py2.py3-none-any.whl (227kB)
     |################################| 235kB 32.7MB/s
Collecting cycler>=0.10 (from matplotlib)
  Downloading https://files.pythonhosted.org/packages/f7/d2/e07d3ebb2bd7af696440ce7e754c59dd546ffe1bbe732c8ab68b9c834e61/cycler-0.10.0-py2.py3-none-any.whl
Collecting six>=1.5 (from python-dateutil>=2.1->matplotlib)
  Downloading https://files.pythonhosted.org/packages/ee/ff/48bde5c0f013094d729fe4b0316ba2a24774b3ff1c52d924a8a4cb04078a/six-1.15.0-py2.py3-none-any.whl
Installing collected packages: numpy, pyparsing, pillow, kiwisolver, six, python-dateutil, cycler, matplotlib
Successfully installed cycler-0.10.0 kiwisolver-1.3.1 matplotlib-3.3.3 numpy-1.19.5 pillow-8.1.0 pyparsing-2.4.7 python-dateutil-2.8.1 six-1.15.0
WARNING: You are using pip version 19.1.1, however version 20.3.3 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.
[cuzuser@xxxx ~]$ ls my_py3/
PIL                                         matplotlib-3.3.3.dist-info
Pillow-8.1.0.dist-info                      mpl_toolkits
Pillow.libs                                 numpy
__pycache__                                 numpy-1.19.5.dist-info
bin                                         numpy.libs
cycler-0.10.0.dist-info                     pylab.py
cycler.py                                   pyparsing-2.4.7.dist-info
dateutil                                    pyparsing.py
kiwisolver-1.3.1.dist-info                  python_dateutil-2.8.1.dist-info
kiwisolver.cpython-36m-x86_64-linux-gnu.so  six-1.15.0.dist-info
matplotlib                                  six.py
matplotlib-3.3.3-py3.6-nspkg.pth
[cuzuser@xxxx ~]$ cd public_html/teqnobreaker.com/work
[cuzuser@xxxx work]$ pwd
/virtual/cuzuser/public_html/teqnobreaker.com/work
[cuzuser@xxxx work]$ vi draw.py
[cuzuser@xxxx work]$ chmod +x draw.py

draw.py のソースも元記事のものから日本語コメント無しにしたものを載せておきます。
また、元記事とはフォルダ構成が違うのでライブラリ読込パスを「../../../my_py3」としてます。

Python
#!/usr/local/bin/python3
import io
import sys
# add library path
sys.path.append('../../../my_py3')
# import NumPy and Matplotlib
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
# make data
x = np.arange(0, 6, 0.1) # 0 to 6 every 0.1
y1 = np.sin(x)
y2 = np.cos(x)
# plot graph
plt.figure(figsize=(4, 3), dpi=160) # figure size
plt.plot(x, y1, label='sin')
plt.plot(x, y2, linestyle = '--', label='cos') # dashed line
plt.xlabel('x') # x label
plt.ylabel('y') # y label
plt.title('sin & cos') # title
plt.legend() # usage
# make PNG
image = io.BytesIO()
plt.savefig(image, format='png')
image.seek(0)
# HTTP header
sys.stdout.buffer.write(b'Content-Type: image/png\n\n')
# output binary data
sys.stdout.buffer.write(image.read())

そして、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」でアクセス権が無いので見れません。

ソースを見て原因になると思われるものを考えて潰して行きます。

  1. ライブラリの読込に失敗している「../../../my_py3」
    もしかすると、public_html/teqnobreaker.com/ 配下じゃないと参照できないとか?
  2. そもそも外部ライブラリを許してない
    これはそんな制御ができるのかは不明。
  3. ライブラリは読み込めているが画像の出力に失敗している
    ライブラリが古いとかは無いだろうか。

まずは①を確認しようと、~/my_py3public_html/teqnobreaker.com/work 配下に移動して動かしたけど「Internal Server Error」で変わらず。

あ、もしかするとライブラリpython2 用になってたりするのかも?
そもそも、コアサーバーライブラリのインストールはできるもんなんだろうか?
検索すると、以下の記事を発見。

コアサーバーでpythonのpip install方法
独学でプログラミングを勉強している、ざくぺん(@zach_penguin)です。 この記事は、「コア...続きを読む

あまり詳しくは書いて無いが他のページなども見た結果、以下がわかった。

  • pip が古い場合があるので最初に pipアップグレードをする
  • --user を付けると自分のホームディレクトリの .local 配下にライブラリはインストールされる
  • .local 配下だとライブラリのパスが通ってるのでソースでパスを追加する必要は無し

前回ライブラリをインストールした時のログをよく見ると、しっかり以下の警告が出てるでは無いか。

Bash
WARNING: You are using pip version 19.1.1, however version 20.3.3 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.

ということで、pip のアップデートをして numpymatplotlib をインストールした。

Bash
[cuzuser@xxxx ~]$ python3 -m pip install --upgrade pip --user
Collecting pip
  Downloading https://files.pythonhosted.org/packages/54/eb/4a3642e971f404d69d4f6fa3885559d67562801b99d7592487f1ecc4e017/pip-20.3.3-py2.py3-none-any.whl (1.5MB)
     |################################| 1.5MB 13.0MB/s
Installing collected packages: pip
Successfully installed pip-20.3.3
WARNING: You are using pip version 19.1.1, however version 20.3.3 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.
[cuzuser@xxxx ~]$ python3 -m pip -V
pip 20.3.3 from /virtual/cuzuser/.local/lib/python3.6/site-packages/pip (python 3.6)
[cuzuser@xxxx ~]$ python3 -m pip install numpy matplotlib --user
Collecting matplotlib
  Using cached matplotlib-3.3.3-cp36-cp36m-manylinux1_x86_64.whl (11.6 MB)
Collecting numpy
  Using cached numpy-1.19.5-cp36-cp36m-manylinux2010_x86_64.whl (14.8 MB)
Collecting cycler>=0.10
  Using cached cycler-0.10.0-py2.py3-none-any.whl (6.5 kB)
Requirement already satisfied: six in /usr/local/python3/lib/python3.6/site-packages (from cycler>=0.10->matplotlib) (1.11.0)
Collecting kiwisolver>=1.0.1
  Using cached kiwisolver-1.3.1-cp36-cp36m-manylinux1_x86_64.whl (1.1 MB)
Collecting pillow>=6.2.0
  Using cached Pillow-8.1.0-cp36-cp36m-manylinux1_x86_64.whl (2.2 MB)
Collecting pyparsing!=2.0.4,!=2.1.2,!=2.1.6,>=2.0.3
  Using cached pyparsing-2.4.7-py2.py3-none-any.whl (67 kB)
Collecting python-dateutil>=2.1
  Using cached python_dateutil-2.8.1-py2.py3-none-any.whl (227 kB)
Installing collected packages: python-dateutil, pyparsing, pillow, numpy, kiwisolver, cycler, matplotlib
Successfully installed cycler-0.10.0 kiwisolver-1.3.1 matplotlib-3.3.3 numpy-1.19.5 pillow-8.1.0 pyparsing-2.4.7 python-dateutil-2.8.1
[cuzuser@xxxx ~]$

この後、ライブラリのパスの指定無しで実行するも「Internal Server Error」のまま。

うーん、そもそもライブラリの読込で失敗してたりするのだろうか。
確認するために新しいライブラリを読み込むだけで「Hello, World!」を表示するソースを「draw1.py」として作ってみた。

Python
#!/usr/bin/env python3
import io
import sys
import numpy
import matplotlib
print('Content-Type:text/html')
print('')
print('Hello,World!')

これなら動くだろうと、https://teqnobreaker.com/work/draw1.py を実施してみるが、まさかの「Internal Server Error」。
ということは、ライブラリ読み込みがダメってことなのか!?

そうか、試しにコマンドラインで実行したらエラーがわかるかも。

Bash
[cuzuser@xxxx work]$ ./draw1.py
Content-Type:text/html
Hello,World!
[cuzuser@xxxx work]$

え!?エラーにならない!?
python を直接動かすとエラーにならないのに、httpアクセスでCGIとして動かすとエラーになるということは、httpアクセスの場合のユーザが違うから .local のパスを見てないということか?

pythonライブラリパスsys.path に入ってるそうなので、これを表示すればコマンド起動時とhttpアクセス時のライブラリパスの違いがわかりそう。
ということで sys.path を表示するプログラム「sys_path.py」を作ってみた。

Python
#!/usr/local/bin/python3
import sys
import pprint
print('Content-Type:text/html')
print('')
print('Hello,World!')
pprint.pprint(sys.path)
print('')

まずはこれをコマンドで起動してみる。
なるほど途中に「'/virtual/cuzuser/.local/lib/python3.6/site-packages'」が入ってる。

Bash
[cuzuser@xxxx work]$ ./sys_path.py
Content-Type:text/html
Hello,World!
['/virtual/cuzuser/public_html/teqnobreaker.com/work',
 '/usr/local/python3/lib/python36.zip',
 '/usr/local/python3/lib/python3.6',
 '/usr/local/python3/lib/python3.6/lib-dynload',
 '/virtual/cuzuser/.local/lib/python3.6/site-packages',
 '/usr/local/python3/lib/python3.6/site-packages',
 '/usr/local/python3/lib/python3.6/site-packages/mysqlclient-1.3.4-py3.6-linux-x86_64.egg']
[cuzuser@xxxx work]$

今度はhttpで起動。
あれ!?ちゃんと「'/virtual/cuzuser/.local/lib/python3.6/site-packages'」が入ってる!?
これは、、煮詰まりました。。

正解は?

いろいろ検索してなかなかわからなかったのですが、以下の記事を見てわかりました。

簡単に言うと、処理が重いCGIは応答時間が遅いのでwebサーバーが「Internal Server Error」にしてしまうようでした。。

この記事では解決策として、php経由でxxx.pyを実行する方法が記載されています。
phpの場合は処理が多少遅くてもエラーにならないということですね。

このページにあるサンプルの test.pytest.php などを作って確かめてみると、確かに test.pyhttp起動ではエラーになるけど、test.php経由だと表示されました。

ただ、このサンプルでは test.py の出力結果を test.php で表示するというものなので、draw.py の場合のバイナリ出力を php 側でもらって画像として出すというのを作ろうと試みましたが、自分の技術では上手く作れなかったです。

元のやり方と違うのでイマイチではありますが、draw2.pyimg.png というファイルを出力するようにして、draw2.php img.png を表示するようにすることで動かすことはできました。
とりあえず外部ライブラリが動くことを確認できたので良しとしよう。笑

Python
#!/usr/local/bin/python3
import io
import sys
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
x = np.arange(0, 6, 0.1)
y1 = np.sin(x)
y2 = np.cos(x)
plt.plot(x, y1, label='sin')
plt.plot(x, y2, linestyle = '--', label='cos')
plt.xlabel('x')
plt.ylabel('y')
plt.title('sin & cos')
plt.legend()
plt.savefig("img.png")
PHP
<?php
$data = array();
exec("/virtual/cuzuser/public_html/teqnobreaker.com/work/draw2.py 2>&1", $data);
header('Content-Type: image/png');
readfile('/virtual/cuzuser/public_html/teqnobreaker.com/work/img.png');
?>

画像ではdraw1.phpになってますが文に合わせてdraw2.php にしてます。たしかに表示が遅いです。
https://teqnobreaker.com/work/draw2.php

コメント

タイトルとURLをコピーしました