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