我有一个目录,我们称之为Storage
,其中包含mypackage-xxyyzzww
等名称拙劣的软件包,当然Storage
位于我的PYTHONPATH
上。由于包具有长的不可知名称,因此所有包都符号链接到更友好的名称,例如mypackage
。
现在,我不想依赖文件系统符号链接来执行此操作,而是尝试使用sys.path
和sys.modules
。目前我正在做这样的事情:
import imp
imp.load_package('mypackage', 'Storage/mypackage-xxyyzzww')
以这种方式做事有多糟糕,将来有可能会破裂吗?有趣的是,文档中甚至没有提到imp.load_package
函数。
编辑:除了不依赖于符号链接外,我再也不能使用PYTHONPATH
变量了。
答案 0 :(得分:9)
您可以为导入的模块指定不同的名称,而不是使用imp
。
import mypackage_xxyyzzww as mypackage
如果您在__init__.py
内创建了Storage
文件,则可以添加上述几行,以便于导入。
<强>存储/ __初始化__吡啶强>:
import mypackage_xxyyzzww as mypackage
import otherpackage_xxyyzzww as otherpackage
<强>解释强>
>>> from Storage import mypackage, otherpackage
答案 1 :(得分:3)
importlib可能更合适,因为它使用/实现PEP302机制。
按照DictImporter示例,但覆盖find_module
以查找真实文件名并将其存储在dict中,然后覆盖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
然后当你import Storage.mypackage
时,python将立即使用你的导入器而不必费心去查看sys.path
这不起作用。上面的代码可以在Storage下导入普通模块,而不需要存储在sys.path上,但3.1和2.6似乎都忽略了PEP302中提到的 loader 属性。 如果我取消注释sys.meta_path行,3.1使用StackOverflow消失,2.6使用ImportError消失。嗯...我现在没时间了,但可能会稍后再看。
答案 2 :(得分:0)
包只是命名空间中的条目。您不应该使用任何非合法的python变量名称来命名路径组件。