Python 相对 __import__
Python relative __import__
假设我有一个包含以下文件的模块包。一个空文件 C:\codes\package\__init__.py
和一些重要文件:
一个位于 C:\codes\package\first.py
def f():
print 'a'
另一个位于C:\codes\package\second.py
def f():
print 'b'
还有第三个文件:C:\codes\package\general.py
,代码如下
def myPrint(module_name):
module = __import__(module_name)
module.f()
if __name__ == '__main__':
myPrint('first')
myPrint('second')
当我运行后一个文件时,一切正常。但是,如果我尝试执行包含
的文件 C:\codes\test.py
if __name__ == '__main__':
from package import general
general.myPrint('first')
general.myPrint('second')
我收到导入错误 ImportError: No module named first
。如何解决这个问题?
首先,我怀疑您忘记提到您有一个(可能是空的)文件 package\__init__.py
,它使 package
成为一个包。否则,from package import general
将无法工作。
就您在包裹中而言,第二种情况与第一种情况不同。在一个包中,你不会做 import first
,而是 import .first
。后者的等效项描述为 here ,您可以在其中添加 level=1
作为参数,或者(但我不确定)将 .first
放入字符串并设置 level
到 -1
(如果它不是默认值,文档中并不清楚)。
此外,您至少要提供globals()
,所以右边的行是
module = __import__(module_name, globals(), level=1)
我找到了这个解决方案 here。
在您的情况下,您应该从 package
导入 module_name
。使用 fromlist
参数:
getattr(__import__("package", fromlist=[module_name]), module_name)
假设您使用的是 Python 3,那只是因为此版本放弃了对 implicit relative imports 的支持。使用 Python 2 它会工作得很好。
所以要么你需要在 C:\codes\package\general.py
中使用相对导入,这会导致错误调用它,要么将你的包添加到路径中。有点脏,但工作黑客将是:
def myPrint(module_name):
pkg = os.path.dirname(__file__)
sys.path.insert(0, pkg)
try:
module = __import__(module_name)
except:
raise
finally:
sys.path.remove(pkg)
module.f()
也许您可以使用 importlib
模块实现更清晰的实现。
假设我有一个包含以下文件的模块包。一个空文件 C:\codes\package\__init__.py
和一些重要文件:
一个位于 C:\codes\package\first.py
def f():
print 'a'
另一个位于C:\codes\package\second.py
def f():
print 'b'
还有第三个文件:C:\codes\package\general.py
,代码如下
def myPrint(module_name):
module = __import__(module_name)
module.f()
if __name__ == '__main__':
myPrint('first')
myPrint('second')
当我运行后一个文件时,一切正常。但是,如果我尝试执行包含
的文件C:\codes\test.py
if __name__ == '__main__':
from package import general
general.myPrint('first')
general.myPrint('second')
我收到导入错误 ImportError: No module named first
。如何解决这个问题?
首先,我怀疑您忘记提到您有一个(可能是空的)文件 package\__init__.py
,它使 package
成为一个包。否则,from package import general
将无法工作。
就您在包裹中而言,第二种情况与第一种情况不同。在一个包中,你不会做 import first
,而是 import .first
。后者的等效项描述为 here ,您可以在其中添加 level=1
作为参数,或者(但我不确定)将 .first
放入字符串并设置 level
到 -1
(如果它不是默认值,文档中并不清楚)。
此外,您至少要提供globals()
,所以右边的行是
module = __import__(module_name, globals(), level=1)
我找到了这个解决方案 here。
在您的情况下,您应该从 package
导入 module_name
。使用 fromlist
参数:
getattr(__import__("package", fromlist=[module_name]), module_name)
假设您使用的是 Python 3,那只是因为此版本放弃了对 implicit relative imports 的支持。使用 Python 2 它会工作得很好。
所以要么你需要在 C:\codes\package\general.py
中使用相对导入,这会导致错误调用它,要么将你的包添加到路径中。有点脏,但工作黑客将是:
def myPrint(module_name):
pkg = os.path.dirname(__file__)
sys.path.insert(0, pkg)
try:
module = __import__(module_name)
except:
raise
finally:
sys.path.remove(pkg)
module.f()
也许您可以使用 importlib
模块实现更清晰的实现。