摘要

本文详解 Python 模块导入from xxx import xxx、from xxx import *规则,系统讲解Python 包概念、__init__.py作用、项目目录搭建、包两种导入方式(绝对导入、相对导入),罗列导包常见踩坑点,附带完整可运行源码,适合零基础学习 Python 包管理。

关键字:Python 包、init.py、相对导入、绝对导入、模块导入、all

一、from xxx import * 与 all 导入规则

1.1 核心规则

  1. from 模块 import *:一次性导入模块所有可用变量、函数

  2. 模块内定义__all__ = ["变量名","函数名"]:*只会导入列表内声明内容,不在列表中的内容无法通过*导入

  3. 无__all__:默认导出模块全部全局成员

1.2 示例代码

[haha.py](haha.py)

# haha.py
__all__ = ["money", "chi"]
money = 100
​
def chi():
    print("我是吃")
​
def he():
    print("我是呵呵")
[test.py](test.py)

# test.py
from haha import *
chi()
print(money)
# he()  # 报错,he不在__all__列表中

二、Python 包基础概念

2.1 什么是包

包是使用.划分命名空间的文件夹,Python2 必须带**__init__.py文件,Python3 可省略,但规范开发建议所有包目录都创建__init__.py**;

包本质是特殊模块,创建目的:分类管理大量模块文件,优化项目目录结构、提升代码可维护性。

2.2 自动创建案例目录结构代码

执行下面代码一键生成示例项目glance包目录:

import os
# 创建多级目录
os.makedirs('glance/api')
os.makedirs('glance/cmd')
os.makedirs('glance/db')
​
# 批量创建__init__.py与业务py文件
file_list = [
    open('glance/__init__.py','w'),
    open('glance/api/__init__.py','w'),
    open('glance/api/policy.py','w'),
    open('glance/api/versions.py','w'),
    open('glance/cmd/__init__.py','w'),
    open('glance/cmd/manage.py','w'),
    open('glance/db/__init__.py','w'),
    open('glance/db/models.py','w')
]
# 关闭所有文件句柄
list(map(lambda f: f.close(), file_list))

2.3 最终项目目录结构

目录 / 文件说明
glance/顶级包
├─init.py包初始化文件
├─api/子包 api
│ ├─init.py子包初始化
│ ├─[policy.py](policy.py)业务模块
│ └─[versions.py](versions.py)业务模块
├─cmd/子包 cmd
│ ├─init.py子包初始化
│ └─[manage.py](manage.py)业务模块
└─db/子包 db
├─init.py子包初始化
└─[models.py](models.py)业务模块

2.4 填充各模块测试代码

[policy.py](policy.py)
# glance/api/policy.py
def get():
    print('from policy.py')
[versions.py](versions.py)
# glance/api/versions.py
def create_resource(conf):
    print('from version.py: ', conf)
[manage.py](manage.py)
# glance/cmd/manage.py
def main():
    print('from manage.py')
[models.py](models.py)
# glance/db/models.py
def register_models(engine):
    print('from models.py: ', engine)

三、包的两种导入语法:import /from ... import

3.1 import 完整路径导入

# test.py
# 完整层级导入模块
import glance.db.models
glance.db.models.register_models('mysql')

3.2 from xxx import xxx 导入

语法限制:from a.b import c合法;from a import b.c非法,import 后不能带.

# test.py
from glance.api.policy import get
get()

四、init.py 核心作用

4.1 执行时机

首次导入包 / 包子模块时,自动执行当前包下的**__init__.py**,可编写初始化代码、预导入内容、配置__all__控制from 包 import *导出内容。

4.2 _\all\_控制 * 导入示例

glance/init.py

# glance/__init__.py
print("我是glance的__init__.py文件. ")
x = 10

def hehe():
    print("我是呵呵")

def haha():
    print("我是哈哈")

# 限定*导入的内容
__all__ = ['x', "hehe"]
[test.py](test.py)

# test.py
from glance import *
print(x)
hehe()
# haha() # 报错,haha不在__all__内

五、包内:绝对导入 & 相对导入

使用场景:包内部各个子模块之间互相导入

导入类型规则符号
绝对导入以项目顶级包名开头完整路径导入无特殊符号
相对导入.当前目录,..上级目录,只能在包内部使用. / ..

5.1 绝对导入(推荐,无运行限制)

在glance/api/versions.py中导入 cmd 模块:

# glance/api/versions.py
# 绝对导入:从顶层glance开始写全路径
from glance.cmd import manage
manage.main()

5.2 相对导入

# glance/api/versions.py
# .. 代表上级目录glance,跨子包导入
from ..cmd import manage
manage.main()

⚠️ 重要坑:带有相对导入的 py 文件不能直接作为入口脚本运行,否则报错attempted relative import beyond top-level package,只能在外部通过导入包使用。

六、导包高频踩坑点

坑 1:同目录直接 import 模块,外部导包报错

[policy.py](policy.py) 直接写import versions,本地单独运行 policy 正常;外部import glance.api.policy时报错ModuleNotFoundError

# glance/api/policy.py
# 错误写法
import versions

# 正确写法(绝对导入)
from glance.api import versions

原因:单独运行脚本和外部导入时sys.path搜索路径不一致,跨项目导入找不到模块,导包异常优先打印print(sys.path)排查路径。

坑 2:直接 import 顶级包无法调用子模块

# test.py
import glance
# glance.db.models.register_models("mysql") # 报错,默认不会自动加载子包

解决方案:在glance/__init__.py提前导入子包

# glance/__init__.py
# 绝对导入预加载子包
from . import api
from . import cmd
from . import db

七、包导入通用硬性规范

  1. 导入语句中带**.时,.左侧必须是包**,如a.b.c,b 必须是 a 的子包、c 是 b 内模块;

  2. import 包名,命名空间内容来自包下__init__.py;

  3. 不同包下同名模块不会冲突,A.a和B.a分属两个独立命名空间。

结语

本文完整覆盖 Python 包入门全知识点,代码可直接复制运行,掌握__init__.py、绝对 / 相对导入后即可规范搭建大中型 Python 项目目录。

Logo

小龙虾开发者社区是 CSDN 旗下专注 OpenClaw 生态的官方阵地,聚焦技能开发、插件实践与部署教程,为开发者提供可直接落地的方案、工具与交流平台,助力高效构建与落地 AI 应用

更多推荐