我正在使用Python 2。
我发现,当
__all__
未声明时(即仅使用
_functions
但未明确定义
__all__
),from module import *
默认不会传递
__all__
(下划线的“内部”函数)。但是,我还看到即使将
_functions
添加到
__all__
,也没有通过。为了找到这个问题的答案,我在问题中遗漏了哪些词语?这是 Python 3 中持续存在的“问题”(或预期行为?)吗?
我的例子是:
我正在创建内部和外部功能的组合。目前我对这个问题的绕过是将
_functions
(下划线函数,又名“内部函数”,重命名为无下划线)放入
._internal_module_folder
中,然后将
._internal_module_folder
导入到
external_module
中并添加外部函数添加到
__all__
的
external_module
,但忽略内部函数。所以我原来的树(有问题)看起来像这样:
modules_folder/
|---- __init__.py
|---- external_module.py
|---- _internal_module_folder/
|-------- __init__.py
|-------- _internal_module.py
地点:
modules_folder/_internal_module_folder/__init__.py
包含:
from ._internal_module import * # Should import _functions from __all__??
modules_folder/_internal_module_folder/internal_module.py
包含:
__all__ = [
# functions:
'extl_func1',
# _functions:
'_intl_func1',
]
def extl_func1(*args, **kwargs):
pass
def _intl_func1(*args, **kwargs):
pass
modules_folder/__init__.py
包含:
from .external_module import *
modules_folder/external_module.py
包含:
from ._internal_module_folder import *
__all__ = [
# functions:
'extl_func1', # from _internal_module_folder
'extl_func2',
]
def extl_func2(*args, **kwargs):
_intl_func1()
def _intl_func2(*args, **kwargs):
pass
运行时出现错误,指出 _int_func1
不存在,即使它明确位于
__all__
中:
NameError: name '_intl_func1' is not defined
_intl_func
重命名为
intl_func
modules_folder/__init__.py
中的导入更改为
from . import _internal_module as im
from . import _internal_module_folder as im
__all__ = [
# functions:
'extl_func1', # from _internal_module_folder
'extl_func2',
]
# Aliasing the internal module functions to pass to __all__:
extl_func1 = im.extl_func1
def extl_func2(*args, **kwargs):
im.intl_func1()
def _intl_func2(*args, **kwargs):
pass
此 PEP 8 已获批准吗?总结:将
_function
放入
__all__
,但没有传递到
from module import *
。
__all__
传递,即使在
__all__
中明确命名。此信息来自 PEP 8 (
https://peps.python.org/pep-0008/#descriptive-naming-styles)
解决方案的关键部分是从导入全部更改,即:
from ._internal_module_folder import *
使用别名导入模块(也可以不使用别名!):
from . import _internal_module_folder as im # with module aliasing
注意:导入模块时,无需将 _intl_func1
重命名为
intl_func1
,因为导入模块会绕过
__all__
。但是,将外部函数(前面没有下划线的函数)从
_internal_module_folder
传递到
__all__
中的
external_module.py
列表并不是公开外部函数的首选方法,因为很难找到在哪里如果稍后更改函数名称,则会出现错误!导入应由
__init__.py
控制(根据“Dead Simple Python”,2023 年,Jason C. McDonald,第 87-88 页)
因此,
modules_folder/__init__.py
应更改为包含两个模块的外部函数:
from .external_module import *
from ._internal_module_folder import *
在这种情况下 modules_folder/external_module .py
应更改为:
from . import _internal_module_folder as im
__all__ = [
# functions:
'extl_func2', # Only list the external functions from THIS file
]
def extl_func2(*args, **kwargs):
im.intl_func1
def _intl_func2(*args, **kwargs):
pass
或者也可以直接在modules_folder/external_module .py
中导入具体的内部函数,简化_intl_func1
函数调用:
from ._internal_module_folder import _intl_func1 # This does not access the __all__ list!
__all__ = [
# functions:
'extl_func2',
]
def extl_func2(*args, **kwargs):
_intl_func1()
def _intl_func2(*args, **kwargs):
pass