Pythonのライブラリを動的に追加する
January 14, 2009 at 08:44 AM | View Commentsちょっと site.addsitedirについて分らないことがあったのでメモ。
- Python起動時にsiteモジュールは自動的にインポートされる。(-S をつけるとインポートしない)
- site-packages自体とその直下の.pthファイルに書いてあるモジュールをsys.pathに追加する。
を行っています。
後から、「/hoge/my-lib/複数のモジュール」にPATHを通す必要があるとき
sys.path.insert(0, '/hoge/my-lib')
だと上手くいかない。なぜならモジュールの多くは
- my-lib/
- hoge-2.1.1/
/hoge /__init__.py /hogemodule1.py
のような構成になっているので、my-lib直下に__init__.pyが無いためにPythonがその下のモジュールを見つけられないためだ。
どうしても、sys.pathを使う場合は
import sys
import os
sys.path.insert(0, os.path.join('/hoge/my-lib/hoge-2.1.1'))
sys.path.insert(0, os.path.join('/hoge/my-lib/fuga-2.2.1'))
sys.path.insert(0, os.path.join('/hoge/my-lib/hum-1.1.3'))
のように一つ一つのモジュールを指定してあげる必要がある。
しかし、それだと非常に面倒なので/hoge/my-lib/mypackage.pthのような.pthファイルに
hoge-2.1.1
huga-2.2.1
hum-1.1.3
とテキストファイルを用意し
from site import addsitedir
addsitedir('/hoge/my-lib')
と、してあげると.pthファイルに書いてあるモジュールを一つ一つにPATHを通してくれる。
pinaxのサンプルプロジェクトについているmanage.pyは以下のように拡張されているのだが、addsitedir()とsys.pathの共存はこのようにするらしい。
path = addsitedir(join(settings.PINAX_ROOT, "libs/external_libs"), set())
if path:
sys.path = list(path) + sys.path
sys.path.insert(0, join(settings.PINAX_ROOT, "apps/external_apps"))
sys.path.insert(0, join(settings.PINAX_ROOT, "apps/local_apps"))
sys.path.insert(0, join(settings.PROJECT_ROOT, "apps"))
addsitedirの第2引数にset()をつけている。
set()が無いとNoneで返されてしまうのだが、set()を渡すことで追加したモジュールのpathのsetを返してくれる。
それをsys.pathに追加して、さらにsys.path.insertで別のものを追加してるようだ。
ちなみにpthファイルを手で書くのが面倒だと思ってたらpinaxのapps/external_libsにupdate.shというシェルスクリプトがあった
#!/bin/sh
ls -1 `dirname $0` | grep -v packages.pth | grep -v update.sh > `dirname $0`/packages.pth
cat `dirname $0`/packages.pth
これは便利だ。
以下、site.pyのaddsitedir関数の部分。
def addsitedir(sitedir, known_paths=None):
"""Add 'sitedir' argument to sys.path if missing and handle .pth files in
'sitedir'"""
if known_paths is None:
known_paths = _init_pathinfo()
reset = 1
else:
reset = 0
sitedir, sitedircase = makepath(sitedir)
if not sitedircase in known_paths:
sys.path.append(sitedir) # Add path component
try:
names = os.listdir(sitedir)
except os.error:
return
names.sort()
for name in names:
if name.endswith(os.extsep + "pth"):
addpackage(sitedir, name, known_paths)
if reset:
known_paths = None
return known_paths
categories:
python
ツイート