我的情况有点不同 - 想要动态导入每个gameX.__init__.py
模块中的 constants.py 名称(见下文),因为静态导入这些名称会使它们永远留在 sys.modules 中(请参阅:我从这个相关问题中挑选的 Beazley摘录) .
这是我的文件夹结构:
game/
__init__.py
game1/
__init__.py
constants.py
...
game2/
__init__.py
constants.py
...
每个都gameX.__init__.py
导出一个 init() 方法 - 所以我最初from .constants import *
在所有gameX.__init__.py
我试图在 init() 方法中移动的方法中都有一个。
我的第一次尝试是:
@@ -275,2 +274,6 @@ def init():
# called instead of 'reload'
+ yak = {}
+ yak.update(locals())
+ from .constants import * # fails here
+ yak = {x: y for x,y in locals() if x not in yak}
+ globals().update(yak)
brec.ModReader.recHeader = RecordHeader
以相当神秘的方式失败:
SyntaxError: import * is not allowed in function 'init' 因为它包含一个带有自由变量的嵌套函数
我可以向你保证那里没有嵌套函数。无论如何,我砍伐并削减并最终得到:
def init():
# ...
from .. import dynamic_import_hack
dynamic_import_hack(__name__)
在哪里game.__init__.py
:
def dynamic_import_hack(package_name):
print __name__ # game.init
print package_name # game.gameX.init
import importlib
constants = importlib.import_module('.constants', package=package_name)
import sys
for k in dir(constants):
if k.startswith('_'): continue
setattr(sys.modules[package_name], k, getattr(constants, k))
(对于 setattr,请参阅如何在运行时向模块添加属性?而对于 getattr,如何动态导入 python 模块函数? -我更喜欢使用这些而不是直接访问__dict__
)
这很有效,并且比接受的答案中的方法更通用,因为它允许您将黑客放在一个地方并从任何模块使用它。但是,我不确定这是实现它的最佳方式 - 本来要问一个问题,但由于它与这个问题重复,我将其发布为答案并希望得到一些反馈。我的问题是:
- 为什么这个“语法错误:函数'init'中不允许导入*”而没有嵌套函数?
- dir 在其文档中有很多警告- 特别是它试图产生最相关的,而不是完整的信息- 这个完整让我有点担心
- 没有内置的方法
import *
吗?即使在 python 3 中?