如何透明地重定向Python导入?

时间:2011-01-31 20:49:41

标签: python python-import

我正在寻找一种方法来模拟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/文件夹(使用相对路径和..),子包也可以工作吗?

6 个答案:

答案 0 :(得分:7)

app3/run.py到达import语句之前,您必须执行某些

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

答案 1 :(得分: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)

答案 2 :(得分:1)

__init__.py添加到python_lib文件夹 app3/run.py包含

import python_lib.my_utils
import os

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

答案 3 :(得分:0)

我对您的目录结构进行了以下更改以简化示例:

  • 创建root / python_lib / __ init __。py
  • 将root / python_lib重命名为root / lib
  • 将root / app3 / lib /替换为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中替换它自己的引用,并引用另一个位置的模块或包。

答案 4 :(得分: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()

答案 5 :(得分:-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 / __初始化__。PY

from os.path import join
__path__.insert(0, join(__path__[0], "..", "..", "python_lib"))