前置き
Google App Engineの料金体系改定によって、いろいろとモチベーションが下がったりもしましたが…。
せっかくPythonをかじりかけたことでもあるので、とりあえず、さくらのレンタルサーバ上でPythonを動かして、いろいろ試せるようにしてみようと思い立ちました。
自宅のPCには一応環境あるのだけれど、公開するには(マシン的に)不安定だし。
さくらのレンタルサーバでは、標準でPython 2.7.2が入っています(2012/3/10現在)。
なので、わざわざ自分のディレクトリに入れなくても……とも思いましたが、lxmlなどの外部モジュールを使おうとすると面倒が多そうな気がしたので、丸ごと入れてしまえという発想だったわけなんですが。
いろいろとはまったわけです、予感どおり。
手順
(username)となっているところは、各自のユーザ名で読み替えてください。
1. Python 2.7.2 をインストール
$ mkdir -p ~/temp $ cd ~/temp $ wget http://www.python.org/ftp/python/2.7.2/Python-2.7.2.tgz $ tar xvfz ./Python-2.7.2.tgz $ cd ./Python-2.7.2 $ ./configure --prefix=$HOME --with-threads --enable-shared $ make $ make install $ ln -s ~/lib/python2.7/ ~/lib/python
自分は"--prefix=$HOME"をつけて、~/ 直下にインストールされるようにしました。なお、作業用ディレクトリとして ~/temp を用意しています。
これで、
- /home/(username)/bin 下にPythonの実行ファイル
- /home/(username)/lib/python2.7 下にライブラリ関係(上記手順では便宜上、~/lib/python というバージョン名無しのシンボリックリンクを作成)
- /home/(username)/share/man/man1 下にマニュアル
が、それぞれインストールされます。
2. 環境変数の変更(.bash_profile編集)
ちなみに自分はcsh→bashに変更して使用しています。cshの人は~/.cshrcの編集になると思いますが、よくわからないです…。
$ vim ~/.bash_profile
で、環境変数を設定している辺りに、
export PYTHONHOME=$HOME export PYTHONPATH=$PYTHONHOME/lib/python export LD_LIBRARY_PATH=$PYTHONHOME/lib:$LD_LIBRARY_PATH export LIBRARY_PATH=$PYTHONHOME/lib:$LIBRARY_PATH export PATH=$HOME/bin:$HOME/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/usr/games:/usr/local/sbin:/usr/local/bin:/usr/X11R6/bin:$PATH
のようにPYTHONHOME、PYTHONPATH、LD_LIBRARY_PATH、LIBRARY_PATHを設定し、PATHの先頭に$HOME/binを付け加え、
$ source ~/.bash_profile
で反映。
3. easy_installのインストール
$ cd ~/temp $ wget http://peak.telecommunity.com/dist/ez_setup.py $ python ez_setup.py
4. 外部モジュールのインストール
$ easy_install -UZ lxml $ easy_install -UZ jinja2 $ easy_install -UZ MySQL-python
などなど、後はお好みで必要な外部モジュールをインストール。
なお、easy_install で導入した外部モジュールは、
- /home/(username)/lib/python2.7/site-packages/
に入るようになります。
CGIスクリプトを書くときの注意
- 拡張子は .cgi に。
- パーミッションは 705(755,700)等に設定(suEXECによる制限と思われる)。
- 1行目(シバン・shebang)には LD_LIBRARY_PATH 環境変数の設定をし、インストールしたPython実行ファイルへのPATHを書くこと。
3. ですが、具体的には、1行目を
#! /usr/bin/env -S LD_LIBRARY_PATH=/home/(username)/lib /home/(username)/bin/python
のようにする、ということです。
気になる人は、他の環境変数(PYTHONHOME、PYTHONPATH、LIBRARY_PATH)も追加してもよいですが、少なくとも LD_LIBRARY_PATH だけは無いと、当方の環境では動きませんでした。
具体例
実際にレンタルサーバ上においてあるPythonのCGIファイルです(動作確認可)。
外部モジュールとしてeasy_installした、lxmlおよびjinja(Jinja2)を使用しています。
#! /usr/bin/env -S LD_LIBRARY_PATH=/home/furyu-tei/lib PYTHONHOME=/home/furyu-tei PYTHONPATH=/home/furyu-tei/lib/python LIBRARY_PATH=/home/furyu-tei/lib /home/furyu-tei/bin/python # -*- coding: utf-8 -*- # ■ さくらレンタルサーバのユーザディレクトリ上に Python をインストールして外部モジュールを動かす例 import os import urllib2 import lxml.html import platform from jinja2 import Environment, FileSystemLoader TPL_FILE = 'test-py27_userdir.tpl' TGT_URL = 'http://www.sakura.ne.jp/' def guess_autoescape(template_name): if template_name is None or '.' not in template_name: return False ext = template_name.rsplit('.', 1)[1] return ext in ('html', 'htm', 'xml', 'tpl') if __name__ == '__main__': rsp = urllib2.urlopen(TGT_URL) content = rsp.read() document = lxml.html.fromstring(content) document.make_links_absolute(TGT_URL) try: page_title = document.xpath('//title')[0].text except: page_title = u'(タイトル不明)' links = document.xpath('//a') template = Environment(loader=FileSystemLoader(os.getcwd()),extensions=['jinja2.ext.autoescape'],autoescape=guess_autoescape).get_template(TPL_FILE) tvalue = dict( title = u'『さくらインターネット』レンタルサーバのユーザディレクトリ上に入れたPython%(ver)sで動作' % dict(ver=platform.python_version()), sub_title1 = u'環境変数', env_list = sorted([(name,os.environ[name]) for name in os.environ]), sub_title2 = u'lxmlの試行(『%(title)s』(%(url)s)上リンクのURL)' % dict(title=page_title, url=TGT_URL), url_list = sorted(list(set([l.get('href','') for l in links]))), ) print 'Status: 200 OK' print 'Content-Type:text/html; charset=utf-8' print '' print template.render(tvalue).encode('utf-8','ignore') #■ end of file
はまったところ
モジュールによっては、うまくインストールできない場合有り
たとえば、MySQL-python(MySQLdb) を入れようとすると、コンパイル(リンク)エラー発生。
$ easy_install -UZ MySQL-python : (中略) : /usr/bin/ld: cannot find -lpython2.7
ちなみに、LD_LIBRARY_PATHはちゃんと設定はされていました。
なので、リンカ(ld)にPATHを教えてあげるため、gccが参照する環境変数である LIBRARY_PATH を
export LIBRARY_PATH=$PYTHONHOME/lib:$LIBRARY_PATH
のように、/home/(username)/lib を参照するよう設定することで、回避できるようになりました。
CGI が動かない…
ローカルでは動作していたものが、ブラウザからアクセスするとエラーに。
すべて 500: Internal Server Errorになりましたが、ログを見ると、シバンの書き方により動作が異なります。
■パターン(1)
#! /usr/bin/env python
の場合は、
Traceback (most recent call last): File "test.cgi", line 8, in <module> import lxml.html ImportError: No module named lxml.html
となり、さくらの標準のPythonが動き、かつ、インストールされていないlxmlが見つからないと言ってます。
ユーザディレクトリ上のpython実行ファイルのフルパスを記載する必要あり。
■パターン(2)
#! /usr/bin/env /home/furyu-tei/bin/python
の場合は、
Traceback (most recent call last): File "test.cgi", line 7, in <module> import urllib2 File "/home/furyu-tei/lib/python2.7/urllib2.py", line 94, in <module> import httplib File "/home/furyu-tei/lib/python2.7/httplib.py", line 69, in <module> from array import array ImportError: /home/furyu-tei/lib/python2.7/lib-dynload/array.so: Undefined symbol "PyUnicodeUCS2_FromUnicode"
となり、ユーザディレクトリに入れたPythonを実行しようとしているが、モジュール読み込み時に不明なシンボルがあると言っています。
ライブラリに対するパスが通っていないと出る→LD_LIBRARY_PATHの設定が必要。
ということで、
■パターン(3)
#! /usr/bin/env -S LD_LIBRARY_PATH=/home/furyu-tei/lib /home/furyu-tei/bin/python
とすることにより、正常に動作するようになりました。
参考にしたページ
- さくらレンタルサーバのpythonでMySQLdbを: わにざっき
- さくらのレンタルサーバで Python 外部モジュールを使う
- 「「さくらのレンタルサーバ」で Python 外部モジュールを使う」について - Visitors’ Book - emptypage.jp
あと、cshからbashへの変更、viからvimへの変更は
辺りを参照。
vim導入はこちらで記事にしたのだけれど、csh→bashは記事書き損ねていた。当時のメモもない…。