我有一个目录,让我们把它称为Storage包含笨拙名字的包mypackage-xxyyzzww,当然Storage是我的PYTHONPATH.由于包具有很长的不可知名称,因此所有包都符号链接到更友好的名称,例如mypackage.
现在,我不想依靠文件系统的符号链接要做到这一点,而不是我试图与周围碴sys.path和sys.modules.目前我正在做这样的事情:
import imp
imp.load_package('mypackage', 'Storage/mypackage-xxyyzzww')
Run Code Online (Sandbox Code Playgroud)
以这种方式做事有多糟糕,未来有可能会破裂吗?有趣的是,imp.load_package文档中甚至没有提及函数.
编辑:除了不依赖于符号链接,我不能再使用PYTHONPATH变量了.
imp您可以为导入的模块指定不同的名称,而不是使用.
import mypackage_xxyyzzww as mypackage
Run Code Online (Sandbox Code Playgroud)
如果您随后在其中创建了一个__init__.py文件Storage,则可以添加上述几行以使导入更容易.
存储/ __ init__.py:
import mypackage_xxyyzzww as mypackage
import otherpackage_xxyyzzww as otherpackage
Run Code Online (Sandbox Code Playgroud)
解释:
>>> from Storage import mypackage, otherpackage
Run Code Online (Sandbox Code Playgroud)
importlib可能更合适,因为它使用/实现了PEP302机制。
遵循 DictImporter 示例,但重写find_module以查找真实文件名并将其存储在字典中,然后重写load_module以从找到的文件中获取代码。
创建存储模块后,您不需要使用 sys.path
#from importlib import abc
import imp
import os
import sys
import logging
logging.basicConfig(level=logging.DEBUG)
dprint = logging.debug
class MyImporter(object):
def __init__(self,path):
self.path=path
self.names = {}
def find_module(self,fullname,path=None):
dprint("find_module({fullname},{path})".format(**locals()))
ml = imp.find_module(fullname,path)
dprint(repr(ml))
raise ImportError
def load_module(self,fullname):
dprint("load_module({fullname})".format(**locals()))
return imp.load_module(fullname)
raise ImportError
def load_storage( path, modname=None ):
if modname is None:
modname = os.path.basename(path)
mod = imp.new_module(modname)
sys.modules[modname] = mod
assert mod.__name__== modname
mod.__path__=[path]
#sys.meta_path.append(MyImporter(path))
mod.__loader__= MyImporter(path)
return mod
if __name__=="__main__":
load_storage("arbitrary-path-to-code/Storage")
from Storage import plain
from Storage import mypkg
Run Code Online (Sandbox Code Playgroud)
然后当你这样做时import Storage.mypackage,python将立即使用你的导入器而无需费心去查看sys.path
那是行不通的。上面的代码确实可以在 Storage 下导入普通模块,而不需要 Storage 位于 sys.path 上,但 3.1 和 2.6 似乎都忽略了PEP302 中提到的loader属性。如果我取消注释 sys.meta_path 行,3.1 会因 StackOverflow 终止,2.6 则会因 ImportError 终止。嗯...我现在没时间了,但稍后可能会看一下。