2011-01-31 8 views
7

私はPythonのインポートのためのシンボリックリンクをエミュレートする方法を探しています。私は、ファイルを複製することなく、その場で次のフォルダ構造を解凍できるようにしたいと思います:Pythonのインポートをどのように透過的にリダイレクトできますか?

root 
├─ python_lib 
│ └─ my_utils 
│  ├─ __init__.py 
│  └─ etc.py 
├─ app1 
├─ app2 
└─ app3 
    ├─ lib 
    │ ├─ __init__.py 
    │ └─ my_utils.py 
    └─ run.py 

app3/run.pyはこれを含んでいます

from lib.my_utils import etc 

etc.pancakes() 

私はに位置etcを使用するコードが欲しいですpython_lib/my_utils/app3/lib/my_utils.pyに置くことができるものはありますか?そのため、Python> = 3.1が(相対パスと..を使用して)python_lib/my_utils/フォルダを透過的にインポートし、サブパッケージも機能しますか?

答えて

3

sys.pathにこのパスを追加する必要があります。たとえば:

lib_path = os.path.abspath(os.path.split(os.getcwd()+"/"+sys.argv[0])[0]+"/../_lib/my_utils/") 
sys.path.append(lib_path) 
+0

インポート場所はすでにそれまでに解決されているので、my_utils.py' 'に置く場合、これは動作しないでしょう。これをメインコードの前に実行すると、 'my_utils'の各サブパッケージがPythonのトップレベルに表示され、' my_utils'内の相対インポートが機能しないため、まだ動作しません。 – zildjohn01

+0

私は通常、 'run'スクリプトからパスを設定します。さもなければそれはあまり意味をなさない。 'PYTHONPATH'環境変数で遊んでみることもできます。詳細はこちらhttp://docs.python.org/tutorial/modules.html#the-module-search-path – Elalfer

5

あなたはapp3/run.pyは、import文に到達する前何かを実行する必要があります。

import python_lib 
import sys 
sys.modules['lib'] = python_lib 
# ... 
from lib import etc 
print etc.__file__ 
print dir(etc) 
0

私は例を単純化するために、あなたのディレクトリ構造を次のように変更を加えた:

  • ルートを作成/ python_lib/__
  • リネームルート/ python_lib init__.pyにルート/ libに
  • に置き換えますroot/app3/lib/with lib.py

次のコードをroot/app3/lib.pyに置きます。

import os 
import sys 

pth = os.path.sep.join(sys.argv[0].split(os.path.sep)[0:-2]) 
sys.path.insert(0, pth) 
del sys.modules[__name__] 
import lib 

本質的に、sys.modules内の独自の参照を別の場所のモジュールまたはパッケージへの参照で置き換えるダミーモジュールがあります。

0

これはいかがですか? (はい、app3/lib/my_utils.pyでそれを置く。)

import os 
_f = os.path.realpath(__file__) 
_f = os.path.dirname(_f) 
_f = os.path.dirname(_f) 
_f = os.path.dirname(_f) 
_f = os.path.join(_f, 'python_lib') 
def f(): 
    path = sys.path 
    path.insert(0, _f) 
    sys.modules['lib.my_utils'] = __import__('my_utils') 
    path.pop(0) 
f() 
1

python_libフォルダ app3/run.py__init__.pyを追加非常に遅く、これに

import python_lib.my_utils 
import os 

sys.modules['lib.my_utils'] = python_lib.my_utils 
-1

が含まれているが、これは非常に簡単です。パッケージの__path__属性を変更して、モジュールがあるフォルダを指すようにするだけです。これには、モジュール(すなわち、__init__.pyのフォルダ)だけでなく、libがパッケージになる必要があります。デフォルトで__path__は、パッケージであるフォルダのパスを含む1つの要素リストです(['/path/to/lib'])。つまり、デフォルトでは、pythonはモジュールフォルダ内のサブモジュールを検索します(これは非常に論理的な処理のようです)。

パスの内容を任意の場所に変更できますが、絶対パスが必要です。 だけを追加する場合は、path/to/lib_python、次にpythonはlibを最初に検索し、my_utils.pyを見つけて停止します。その場合はmy_utils.pyを削除するか、新しいパスを__path__の先頭に置き、最初に場所を検索する必要があります。これはまた、libフォルダが共有ライブラリへの独自の補足モジュールを含むことができ、それでも動作することを意味します。実際に

のlib/__ init__.py

from os.path import join 
__path__.insert(0, join(__path__[0], "..", "..", "python_lib")) 
関連する問題