能否使用Python 相对导入将当前模块的__init__ 文件导入到特定名称下?
Can you use Python relative imports to import the __init__ file of the current module under a specific name?
假设我有一个包含两个文件的模块,如下所示:
mymodule
|-- __init__.py
`-- submodule.py
mymodule/__init__.py
包含:
SOME_CONSTANT_ONE = 1
SOME_CONSTANT_TWO = 2
SOME_CONSTANT_THREE = 3
...
SOME_CONSTANT_ONE_HUNDRED = 100
def initialize():
pass # do some stuff
def support_function():
pass # something that lots of other functions might need
我已经知道我可以使用相对导入从 __init__.py
文件中引入 特定的 对象,如下所示:
submodule.py:
from . import initialize, support_function
def do_work():
initialize() # initialize the module
print(support_function()) # do something with the support function
但现在我想知道的是,我是否可以从 __init__.py
文件中导入 所有 常量,但同时让它们出现在命名空间中。
什么行不通(我有什么 tried/considered):
import mymodule as outer_module
有效,因为导入系统已经知道模块在哪里。但是,如果我需要更改外部模块的名称,该代码就会中断。
import . as outer_module
没用。
- 执行
from . import *
确实有效,但会将 __init__.py
中的所有对象放入当前命名空间而不是子命名空间。
- 做
from . import SOME_CONSTANT_ONE as outer_constant_1, SOME_CONSTANT_TWO as outer_constant_2, SOME_CONSTANT_THREE as outer_constant_3, ...
是丑陋的,如果稍后在 __init__.py
中定义它们,则不会引入任何新常量。
我真正想要的是这样的:
submodule.py:
SOME_CONSTANT_ONE = "one!" # We don't want to clobber this.
import . as outer_module # this does not work, but it illustrates what is desired.
def do_work():
print(SOME_CONSTANT_ONE) # should print "one!"
print(outer_module.SOME_CONSTANT_ONE) # should print "1"
我知道我可以将所有常量移动到一个 constants.py
文件,然后我应该可以用 from . import constants (as something)
导入它,但我正在处理现有代码并进行更改需要大量的重构。虽然这不是一个坏主意,但我想知道,鉴于 Python 确实有办法导入单个对象,并且还可以通过名称 将整个模块 导入显式name,如果我可以用 importlib
做一些事情来完成将所有内容从 __init__.py
导入命名空间?
I could move all of the constants to a constants.py
file and then I should be able to import it with from . import constants (as something)
but I'm working on existing code and making that change would require a lot of refactoring
您仍然可以将常量重构到新的 constants.py
模块中。要支持依赖于 __init__.py
的现有代码,您可以将常量导入 __init__.py
# constants.py
SOME_CONSTANT_ONE = 1
SOME_CONSTANT_TWO = 2
SOME_CONSTANT_THREE = 3
... # etc
# __init__.py
from .constants import *
# submodule.py
SOME_CONSTANT_ONE = 'dont clobber me!'
from . import constants as something
print(something.SOME_CONSTANT_ONE) # Yay namespaces
# existing_code.py
from . import SOME_CONSTANT_ONE
# still works!
# no refactor required!
通常 来说,__init__.py
文件通常完全是空的,没有任何内容直接定义在那里。如果 __init__.py
中有内容,它们通常是从包中导入的。
加载器设置__package__
,您可以使用:
import sys
SOME_CONSTANT_ONE = "one!" # We don't want to clobber this.
outer_module = sys.modules[__package__]
def do_work():
print(SOME_CONSTANT_ONE) # should print "one!"
print(outer_module.SOME_CONSTANT_ONE) # should print "1"
这正是相关导入所基于的属性。
有关详细信息,请参阅 PEP 366。
但是,我真的认为另一个答案建议的向后兼容重构可能是更好的方法。
假设我有一个包含两个文件的模块,如下所示:
mymodule
|-- __init__.py
`-- submodule.py
mymodule/__init__.py
包含:
SOME_CONSTANT_ONE = 1
SOME_CONSTANT_TWO = 2
SOME_CONSTANT_THREE = 3
...
SOME_CONSTANT_ONE_HUNDRED = 100
def initialize():
pass # do some stuff
def support_function():
pass # something that lots of other functions might need
我已经知道我可以使用相对导入从 __init__.py
文件中引入 特定的 对象,如下所示:
submodule.py:
from . import initialize, support_function
def do_work():
initialize() # initialize the module
print(support_function()) # do something with the support function
但现在我想知道的是,我是否可以从 __init__.py
文件中导入 所有 常量,但同时让它们出现在命名空间中。
什么行不通(我有什么 tried/considered):
import mymodule as outer_module
有效,因为导入系统已经知道模块在哪里。但是,如果我需要更改外部模块的名称,该代码就会中断。import . as outer_module
没用。- 执行
from . import *
确实有效,但会将__init__.py
中的所有对象放入当前命名空间而不是子命名空间。 - 做
from . import SOME_CONSTANT_ONE as outer_constant_1, SOME_CONSTANT_TWO as outer_constant_2, SOME_CONSTANT_THREE as outer_constant_3, ...
是丑陋的,如果稍后在__init__.py
中定义它们,则不会引入任何新常量。
我真正想要的是这样的:
submodule.py:
SOME_CONSTANT_ONE = "one!" # We don't want to clobber this.
import . as outer_module # this does not work, but it illustrates what is desired.
def do_work():
print(SOME_CONSTANT_ONE) # should print "one!"
print(outer_module.SOME_CONSTANT_ONE) # should print "1"
我知道我可以将所有常量移动到一个 constants.py
文件,然后我应该可以用 from . import constants (as something)
导入它,但我正在处理现有代码并进行更改需要大量的重构。虽然这不是一个坏主意,但我想知道,鉴于 Python 确实有办法导入单个对象,并且还可以通过名称 将整个模块 导入显式name,如果我可以用 importlib
做一些事情来完成将所有内容从 __init__.py
导入命名空间?
I could move all of the constants to a
constants.py
file and then I should be able to import it withfrom . import constants (as something)
but I'm working on existing code and making that change would require a lot of refactoring
您仍然可以将常量重构到新的 constants.py
模块中。要支持依赖于 __init__.py
的现有代码,您可以将常量导入 __init__.py
# constants.py
SOME_CONSTANT_ONE = 1
SOME_CONSTANT_TWO = 2
SOME_CONSTANT_THREE = 3
... # etc
# __init__.py
from .constants import *
# submodule.py
SOME_CONSTANT_ONE = 'dont clobber me!'
from . import constants as something
print(something.SOME_CONSTANT_ONE) # Yay namespaces
# existing_code.py
from . import SOME_CONSTANT_ONE
# still works!
# no refactor required!
通常 来说,__init__.py
文件通常完全是空的,没有任何内容直接定义在那里。如果 __init__.py
中有内容,它们通常是从包中导入的。
加载器设置__package__
,您可以使用:
import sys
SOME_CONSTANT_ONE = "one!" # We don't want to clobber this.
outer_module = sys.modules[__package__]
def do_work():
print(SOME_CONSTANT_ONE) # should print "one!"
print(outer_module.SOME_CONSTANT_ONE) # should print "1"
这正是相关导入所基于的属性。 有关详细信息,请参阅 PEP 366。
但是,我真的认为另一个答案建议的向后兼容重构可能是更好的方法。