随着项目代码量增长,把所有代码写在一个文件里显然不现实。模块和包就是 Python 提供的代码组织方式——模块让你按功能拆分文件,包让你按层级管理模块。掌握它们,才能从"写脚本"迈向"做项目"。
Python 中一个以 .py 结尾的文件就是一个模块,模块中定义了变量、函数等来实现一些类似的功能。Python 有很多自带的模块(标准库)和第三方模块,一个模块可以被其他模块引用,实现了代码的复用性。
# 每一个 .py 文件就是一个模块# 比如 math_utils.py 中定义了数学工具函数# 其他文件可以通过 import 来使用这些函数# 标准库模块示例import os # 操作系统接口import json # JSON 处理import datetime # 日期时间import random # 随机数
💡 小贴士
模块名应简短、全小写,避免下划线开头(如 _foo 是私有模块的约定)。测试项目中常用的命名方式:login_helper.py、api_client.py、test_data.py。
包是存放模块的文件夹,包中包含 __init__.py 和其他模块。__init__.py 可为空也可定义属性和方法。
在 Python 3.3 之前的版本,一个文件夹中只有包含 __init__.py,其他程序才能从该文件夹引入相应的模块、函数等;之后的版本没有 __init__.py 也能正常导入。
⚠️ 踩坑经验
虽然 Python 3.3+ 不强制要求 __init__.py,但强烈建议保留!它可以控制包的导出范围(__all__),也能避免 IDE 识别混乱和隐式命名空间包带来的导入歧义。
在 PyCharm 中创建包和模块非常简单,跟着步骤操作即可。
① 打开 PyCharm,选中项目② 右击鼠标 → New → Python Package③ 填好包名后点击 OK,PyCharm 会自动创建 __init__.py
① 选中刚创建的包② 右击鼠标 → New → Python File③ 填好模块名后点击 OK
package/├── pg1/│ ├── __init__.py│ ├── a.py│ └── b.py└── pg2/ ├── __init__.py ├── c.py └── d.py
# a.pydef a(): print('a')# b.pydef b(): print('b')# c.pydef c(): print('c')# d.pydef d(): print('d')
从包中引入模块有两种主要方式:import ... 和 from ... import ...。
# ===== 1. import 方式 =====# a 模块中引入 b 模块import pg1.bpg1.b.b() # 调用时需要加完整前缀# a 模块中引入 c 模块import pg2.cpg2.c.c() # 调用时需要加完整前缀# 同时引入多个模块import pg2.c, pg2.dpg2.c.c()pg2.d.d()# ===== 2. from ... import 方式 =====# 从包中引入模块from pg1 import bb.b() # 直接用模块名调用# 引入多个模块from pg2 import c, dc.c()d.d()# 引入包下所有模块from pg2 import *# 直接引入模块中的函数from pg2.d import dd() # 直接调用函数,无需前缀
💡 小贴士
from ... import * 看似方便,但会导入所有公开名称,容易造成命名冲突且降低代码可读性。推荐显式写出要导入的名称,团队协作时一目了然。
在实际测试项目中,合理的包结构能让代码清晰可维护。下面是一个典型的自动化测试项目结构:
auto_test/ # 项目根目录├── config/ # 配置包│ ├── __init__.py│ ├── settings.py # 环境配置│ └── data.py # 测试数据├── utils/ # 工具包│ ├── __init__.py│ ├── logger.py # 日志工具│ ├── request.py # 请求封装│ └── assertion.py # 断言工具├── pages/ # 页面对象包│ ├── __init__.py│ ├── login_page.py # 登录页│ └── home_page.py # 首页├── tests/ # 测试用例包│ ├── __init__.py│ ├── test_login.py # 登录测试│ └── test_search.py # 搜索测试├── conftest.py # pytest 固件└── run.py # 入口文件
# tests/test_login.py 中的引用方式# 引入配置from config.settings import BASE_URL, TIMEOUT# 引入工具from utils.logger import logfrom utils.request import send_request# 引入页面对象from pages.login_page import LoginPagedef test_login(): """登录测试用例""" log.info(f"访问: {BASE_URL}") page = LoginPage() page.login("admin", "123456") assert page.is_login_success()
⚠️ 踩坑经验
跨包导入时,经常遇到 ModuleNotFoundError,通常是因为 Python 找不到模块路径。解决办法:① 确保项目根目录在 sys.path 中;② 用 __init__.py 标记包;③ 避免模块名和标准库重名(如 test.py、email.py)。
💡 给测试工程师的建议
1. 合理分层:config 放配置、utils 放工具、pages 放页面对象、tests 放用例,各司其职2. 避免循环导入:A 导入 B,B 又导入 A,会导致 ImportError,用函数内延迟导入解决3. 命名避免冲突:不要用 test.py、os.py 等与标准库同名的模块名4. 显式导入:优先用 from x import y,少用 import *
模块和包是 Python 项目化的基础,也是测试框架搭建的第一步。学会组织代码,才能写出可维护、可扩展的自动化项目!
Python 学习笔记系列 | 第十篇