You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python中加入__all__的_func无法被import *导入的问题

问题

我使用的是Python 2,已知未显式声明__all__时,from module import *默认不会导入以下划线开头的“内部”函数(_functions),但即便将_func加入__all__,仍无法被导入。想请教两个问题:

  1. 查找该问题答案需补充哪些关键词?
  2. 这种情况在Python 3中是预期行为吗?

我的项目结构如下:

modules_folder/
|---- __init__.py
|---- external_module.py
|---- _internal_module_folder/
|-------- __init__.py
|-------- _internal_module.py

各文件代码:

  1. modules_folder/_internal_module_folder/__init__.py:
from ._internal_module import * # 应该从__all__导入_functions?
  1. 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
  1. modules_folder/__init__.py:
from .external_module import *
  1. 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。

我想到的解决方案:

  1. 将_intl_func重命名为intl_func
  2. 修改modules_folder/__init__.py的导入语句:
from . import _internal_module_folder as im
  1. 别名调用内部函数:
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规范,细节上可优化:

  1. 重命名_intl_func为intl_func:PEP 8建议用下划线开头标识仅供模块内部使用的名称,如果该函数确实是内部实现、无需对外暴露,保留_intl_func的命名更符合规范;若需要对外暴露,去掉下划线是合理的。
  2. 导入内部模块并使用别名:PEP 8允许用短别名简化内部模块调用,但建议别名清晰无歧义,比如用internal代替im会更易读。
  3. 显式别名导入函数: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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 07:56:29