Python中加入__all__的_func无法被import *导入的问题
问题
我使用的是Python 2,已知未显式声明__all__时,from module import *默认不会导入以下划线开头的“内部”函数(_functions),但即便将_func加入__all__,仍无法被导入。想请教两个问题:
- 查找该问题答案需补充哪些关键词?
- 这种情况在Python 3中是预期行为吗?
我的项目结构如下:
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 * # 应该从__all__导入_functions?
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', # 来自_internal_module_folder 'extl_func2', ] def extl_func2(*args, **kwargs): _intl_func1() def _intl_func2(*args, **kwargs): pass
运行时出现错误:NameError: name '_intl_func1' is not defined。
我想到的解决方案:
- 将
_intl_func重命名为intl_func - 修改
modules_folder/__init__.py的导入语句:
from . import _internal_module_folder as im
- 别名调用内部函数:
from . import _internal_module_folder as im __all__ = [ # functions: 'extl_func1', # 来自_internal_module_folder 'extl_func2', ] # 给内部模块函数起别名,以便加入__all__: extl_func1 = im.extl_func1 def extl_func2(*args, **kwargs): im._intl_func1() def _intl_func2(*args, **kwargs): pass
请问该方案符合PEP 8规范吗?
解答
一、查找答案的补充关键词
- Python 2
__all__下划线函数导入限制 - Python
from import *内部名称导入规则 - Python 模块导入下划线名称优先级
二、Python 3中的行为
在Python 3中,把下划线开头的名称加入__all__后,from module import *可以正常导入这些名称,这是预期行为。Python 3对__all__的处理更严格,只要是__all__中声明的名称,无论是否以下划线开头,都会被import *导入;而Python 2中import *会优先遵循“下划线开头视为内部名称”的规则,即使该名称在__all__中也会被忽略,这是Python 2的设计特性。
三、解决方案的PEP 8合规性分析
你的方案整体符合PEP 8规范,细节上可优化:
- 重命名
_intl_func为intl_func:PEP 8建议用下划线开头标识仅供模块内部使用的名称,如果该函数确实是内部实现、无需对外暴露,保留_intl_func的命名更符合规范;若需要对外暴露,去掉下划线是合理的。 - 导入内部模块并使用别名:PEP 8允许用短别名简化内部模块调用,但建议别名清晰无歧义,比如用
internal代替im会更易读。 - 显式别名导入函数:
extl_func1 = im.extl_func1这种显式绑定的方式符合PEP 8“显式优于隐式”的原则,比import *更清晰,推荐使用。
针对错误根源,更简洁的合规方案是在external_module.py中直接显式导入所需内部函数,避免import *的模糊性:
from ._internal_module_folder._internal_module import extl_func1, _intl_func1 __all__ = ['extl_func1', 'extl_func2'] def extl_func2(*args, **kwargs): _intl_func1() def _intl_func2(*args, **kwargs): pass
内容的提问来源于stack exchange,提问作者AutumnKome
相关产品推荐
相关产品推荐

