2011-01-31 41 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 2011-01-31 21:05:02

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/__ init__.py
  • 重命名根/ python_lib根/ 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

添加__init__.pypython_lib文件夾 app3/run.py包含

import python_lib.my_utils 
import os 

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

很晚了這一點,但是這是非常容易的。您只需修改包的__path__屬性,使其指向您的模塊所在的文件夾即可。這將需要lib是一個包,而不僅僅是一個模塊(即一個__init__.py的文件夾)。默認情況下,__path__是一個元素列表,其中包含文件夾的路徑 - ['/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"))