Python的学习日志
背景:5月底,主动报名了公司的某IOT项目的出差任务。by the way,其实主要报名原因是考虑到这个项目会有自动化的测试需求,说是出差到北京后主要会负责自动化的内容。
考虑到后面职业未来,功能测试的前景,我觉得自动化前景会稍微好一些。(当然这里涉及到业务线与技术线,二者缺一不可,但技术的机会先出现在我面前我也就只能先把握住我能把握住的机会了)
学习背景:1、有一定的语言基础(C,C++,C#,JAVA,Python)。当然,这里的语言基础主要是指基础语法与一些基本原理,像JAVA的主要框架(SpringBoot等等)其实并没有学习到,主要还是本科学校对于计科这门专业的学习的定位原因吧(这里就不深入讨论了)。2、数据结构、计组、计网的一些理论知识。(本科+考研时的学习内容)
公司给了2个星期左右的时间让我重新捡起Python吧。主要也是项目空闲下来了,新项目又没有开始,所以刚好给了我一个缓冲期(😊真好)所以这个日志一次性更新了很多内容,主要也是我在公司学习时的记录。并用GPT帮我整理了一份markdown格式的
如有遗漏或部分理解的错误,请指正\或发邮件到:603992850@qq.com,在此拜谢
模块1:面向对象高级特性、异常与日志、生成器与装饰器
1.1 __slots__ — 限定实例属性,优化内存
__slots__是类变量,用于规定类实例允许拥有的属性集合。这样实例不能随意添加未在__slots__中声明的属性。- 作用:
- 限制实例属性,避免意外新增多余属性
- 减少内存占用:使用
__slots__后实例不再使用字典存储属性,减少约30%的内存消耗。
- 细节与技巧:
- 导入
types.MethodType,可以给实例动态绑定类中不存在的方法。 - 子类继承父类的
__slots__,但默认子类会获得__dict__,除非子类自己重新声明__slots__。 - 类实例允许的属性是自身的
__slots__+ 父类的__slots__的合集。 __slots__不能限制类本身添加属性,类属性依然可以自由添加。
- 导入
1.2 @property 装饰器 — 方法变属性,控制访问
-
@property是Python内置装饰器,作用是让方法表现得像访问属性一样。 -
作用:
- 把类中的方法变为“只读属性”,避免外部直接调用函数的括号形式。
- 只定义
@property,不定义对应的 setter,会让属性变为只读。
-
注意事项:
-
如果方法名和属性名相同,且方法体里访问了自身属性(例如
return self.x),会导致无限递归。
例如:@property def x(self): return self.x # 无限递归! -
访问
@property属性的速度会比直接访问属性慢一些,因为是调用函数。
-
1.3 多重继承
-
Python支持多重继承,子类可以继承多个父类的功能。相比Java单继承,Python的多重继承更灵活。
-
约定俗成的写法:
-
主父类不写MixIn
-
额外功能用MixIn类提供
-
例如:
class Bat(Mammal, FlyableMixIn): pass
-
-
MixIn类设计原则:
- 只提供特定功能,不单独实例化
- 用于组合拓展类的功能,不构成复杂继承链
1.4 错误处理机制(try-except-else-finally)
-
基本结构:
try: # 可能抛出异常的代码 except SomeError as e: # 捕获并处理SomeError else: # 无异常时执行 finally: # 无论异常与否都会执行 -
细节说明:
raise语句:- 不带参数时,会重新抛出当前异常。
- 可以用来在
except中将一种错误转化成另一种错误抛出。
1.5 Logging模块 — 记录日志的五个重要级别及配置
-
五个级别:
- DEBUG(调试细节)
- INFO(一般信息)
- WARNING(警告)
- ERROR(错误)
- CRITICAL(严重错误)
-
设置日志级别,只记录指定级别及以上的日志:
logging.basicConfig(level=logging.INFO) -
输出日志到文件,格式示例:
logging.basicConfig( filename='app.log', level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s' )- 其中格式字符串由 logging 自动填充:时间、日志器名称、日志级别、日志内容。
1.6 断言(assert)
- 断言是程序中的自检机制,作用类似于
print但更专业。 - 用于检查程序中某些条件是否为真,若断言失败,程序会抛出
AssertionError。 - 常用于单元测试或调试阶段,快速定位错误。
1.7 yield — 生成器函数核心
- 在函数中使用
yield关键字,函数不再是普通函数,而是生成器函数。 - 生成器函数返回一个生成器对象,可以逐个“产出”值,而不是一次性返回所有结果。
- 优势:节省内存,支持惰性计算。
1.8 functools.wraps — 保留装饰器函数元信息
-
在自定义装饰器中,使用
@wraps(func)可让装饰后的函数保持原函数的名字、文档字符串等元信息。 -
有利于调试和文档生成。
-
示例:
from functools import wraps def my_decorator(func): @wraps(func) def wrapper(*args, **kwargs): print(f"调用函数: {func.__name__}") return func(*args, **kwargs) return wrapper
1.9 方法重写
- Python支持类中方法的重写,类似Java。
- 子类可以拓展或修改父类方法的功能,实现多态。
1.10 logging中Logger的使用
- 通过
logging.getLogger("logger名称")获取日志对象。 - 常用Handler:
- StreamHandler — 控制台输出
- FileHandler — 日志文件输出
1.11 pdb 调试工具
- Python内置的单步调试器。
- 可以在代码中插入断点,单步调试程序。
- 现代IDE通常有自带更友好的调试功能,更常用。
模块2:Python测试框架与单元测试、pytest深度解析、自动化测试工具
2.1 单元测试基础 — unittest模块
-
Python内置的单元测试框架,模拟Java的JUnit。
-
主要类:
unittest.TestCase:测试用例基类setUp():每个测试方法执行前调用tearDown():每个测试方法执行后调用
-
结构示例:
import unittest class MyTest(unittest.TestCase): def setUp(self): # 测试准备工作 pass def test_func(self): self.assertEqual(1 + 1, 2) def tearDown(self): # 测试清理工作 pass if __name__ == "__main__": unittest.main() -
常用断言方法:
assertEqual,assertTrue,assertFalse,assertRaises等。
2.2 pytest入门与运行方式
-
轻量且强大的测试框架,兼容unittest。
-
优点:
- 用例函数命名无需继承类,函数名以
test_开头即可 - 支持参数化、夹具,丰富的插件生态
- 友好的断言机制,失败时自动显示表达式详细信息
- 用例函数命名无需继承类,函数名以
-
运行命令:
pytest test_sample.py -
可以直接运行含有
test_前缀的函数,自动发现并执行。
2.3 pytest断言机制详解
-
pytest使用Python的
assert语句替代传统断言方法。 -
失败时,pytest自动解析表达式,展示详细失败原因。
-
例如:
def test_example(): a = 1 b = 2 assert a + b == 4 # 断言失败,pytest自动打印详细表达式和变量值
2.4 pytest夹具(Fixture)
-
夹具是pytest的核心特性,用于测试前准备和后清理工作。
-
通过装饰器
@pytest.fixture定义。 -
作用域可以设置为函数级、模块级、会话级等,复用性强。
-
示例:
import pytest @pytest.fixture def setup_data(): data = {"key": "value"} yield data # 测试后清理代码 def test_use_data(setup_data): assert setup_data["key"] == "value" -
yield前是准备过程,yield后是清理过程。
2.5 pytest参数化
-
通过
@pytest.mark.parametrize装饰器,轻松实现同一测试用例多组数据测试。 -
示例:
@pytest.mark.parametrize("input, expected", [ (1, 2), (3, 4), (5, 6) ]) def test_add_one(input, expected): assert input + 1 == expected
2.6 pytest跳过与预期失败标记
-
标记用例跳过:
import pytest @pytest.mark.skip(reason="跳过该测试") def test_skip(): pass -
标记预期失败:
@pytest.mark.xfail(reason="已知BUG,暂时失败") def test_xfail(): assert False
2.7 pytest命令行常用参数
-
-v:详细模式,显示更多测试信息 -
-k:根据表达式过滤测试用例 -
-m:根据标记过滤用例 -
--maxfail=N:失败达到N个停止执行 -
--tb=short/long/no:控制traceback打印风格 -
示例:
pytest -v -k "test_add" -m "smoke"
2.8 pytest插件系统
-
pytest生态丰富,插件众多。常用插件包括:
pytest-html:生成HTML格式测试报告pytest-xdist:分布式并行执行测试用例pytest-cov:覆盖率统计
-
安装示例:
pip install pytest-html pytest-xdist pytest-cov
2.9 Allure报告集成
-
Allure是美观的测试报告工具,支持pytest。
-
集成步骤:
- 安装allure命令行工具(需系统环境支持)
- 安装pytest-allure-adaptor插件或pytest-allure-plugin(具体版本视环境而定)
- 在测试代码中使用Allure装饰器(例如
@allure.feature、@allure.story等)标记测试用例。 - 运行测试时生成Allure结果数据目录,之后通过命令行生成报告。
-
示例:
pytest --alluredir=./allure-results allure serve ./allure-results
2.10 测试框架封装与自动化测试工具开发
2.10.1 推荐目录结构
project_root/
├── tests/ # 测试用例目录
│ ├── test_login.py
│ ├── test_profile.py
│ └── conftest.py # pytest夹具和全局配置
├── pages/ # 页面对象或接口封装
│ ├── login_page.py
│ └── profile_page.py
├── utils/ # 工具类
│ ├── http_client.py # 封装请求方法
│ └── logger.py # 日志封装
├── data/ # 测试数据,yaml/json等
│ └── test_data.yaml
├── reports/ # 测试报告目录
├── requirements.txt # 依赖包管理
└── pytest.ini # pytest配置文件
2.10.2 核心代码示例
1) 封装HTTP请求(utils/http_client.py)
import requests
class HttpClient:
def __init__(self, base_url):
self.base_url = base_url
def get(self, path, params=None, headers=None):
url = self.base_url + path
response = requests.get(url, params=params, headers=headers)
return response
def post(self, path, json=None, headers=None):
url = self.base_url + path
response = requests.post(url, json=json, headers=headers)
return response
2) 日志封装(utils/logger.py)
import logging
def get_logger(name):
logger = logging.getLogger(name)
if not logger.hasHandlers():
logger.setLevel(logging.DEBUG)
ch = logging.StreamHandler()
formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
ch.setFormatter(formatter)
logger.addHandler(ch)
return logger
3) pytest夹具示例(tests/conftest.py)
import pytest
from utils.http_client import HttpClient
@pytest.fixture(scope="session")
def base_url():
return "https://api.example.com"
@pytest.fixture(scope="session")
def client(base_url):
return HttpClient(base_url)
4) 测试用例示例(tests/test_login.py)
import pytest
def test_login_success(client):
response = client.post("/login", json={"username": "user1", "password": "pass123"})
assert response.status_code == 200
assert response.json().get("token") is not None
@pytest.mark.parametrize("username,password", [
("user1", ""),
("", "pass123"),
("", "")
])
def test_login_fail(client, username, password):
response = client.post("/login", json={"username": username, "password": password})
assert response.status_code == 400
2.10.3 配置pytest.ini示例
[pytest]
addopts = -v --maxfail=3 --tb=short
testpaths = tests
python_files = test_*.py
markers =
smoke: 快速冒烟测试
regression: 回归测试
2.11 接口测试用例设计
- 测试步骤:
- 明确接口功能与参数
- 编写接口请求代码(get/post等)
- 编写断言验证响应状态码、响应体内容
- 覆盖正常用例与异常用例(边界值、无效输入等)
- 使用pytest参数化,提高用例覆盖率
- 可结合Allure进行接口测试报告展示。
2.12 自动化测试中常用工具和库
requests:HTTP请求,接口测试必备pytest:测试执行与管理allure-pytest:报告美化jsonschema:接口响应数据格式校验faker:模拟生成测试数据selenium/Appium:UI自动化测试(非本模块重点)
模块3:Python进阶应用与测试开发实战技巧
3.1 Python文件操作基础与技巧
3.1.1 打开与关闭文件
python复制编辑f = open("data.txt", "r", encoding="utf-8")
content = f.read()
f.close()
推荐使用 with 语法,自动关闭文件:
python复制编辑with open("data.txt", "r", encoding="utf-8") as f:
content = f.read()
3.1.2 常用文件读写方法
read():读取整个文件内容readline():读取一行readlines():按行读取为列表write(str):写入字符串writelines(list):写入多个字符串
3.2 Python序列化:json 与 pickle
3.2.1 JSON模块(常用于接口数据)
python复制编辑import json
data = {"name": "Calvin", "age": 25}
json_str = json.dumps(data) # 序列化为字符串
with open("user.json", "w") as f:
json.dump(data, f) # 写入文件
with open("user.json", "r") as f:
user = json.load(f) # 反序列化
3.2.2 Pickle模块(支持Python对象)
python复制编辑import pickle
obj = {"name": "test", "scores": [90, 80]}
with open("data.pkl", "wb") as f:
pickle.dump(obj, f)
with open("data.pkl", "rb") as f:
result = pickle.load(f)
3.3 正则表达式实战技巧
3.3.1 常见模式符号
| 表达式 | 含义 |
|---|---|
. |
任意字符(换行除外) |
\d |
数字,等价于 [0-9] |
\w |
单词字符 [A-Za-z0-9_] |
* |
0个或多个 |
+ |
1个或多个 |
? |
0个或1个 |
| ` | ` |
^ |
开头匹配 |
$ |
结尾匹配 |
3.3.2 常用方法
python复制编辑import re
text = "My phone number is 18812345678"
pattern = r"\d{11}"
result = re.search(pattern, text)
print(result.group()) # 输出 18812345678
re.match():从头匹配re.search():搜索首个匹配re.findall():返回所有匹配项re.sub(pattern, repl, string):替换匹配字符串
3.4 多线程与多进程编程
3.4.1 threading模块
python复制编辑import threading
def run():
print("Thread running")
t = threading.Thread(target=run)
t.start()
t.join()
threading.Thread()创建线程start()启动线程join()等待线程结束
3.4.2 multiprocessing模块
python复制编辑from multiprocessing import Process
def task():
print("Process task")
p = Process(target=task)
p.start()
p.join()
- 使用多进程避免Python GIL(全局解释器锁)带来的性能瓶颈。
3.5 网络编程基础
3.5.1 socket模块实现通信
python复制编辑import socket
s = socket.socket()
s.connect(('www.example.com', 80))
s.send(b"GET / HTTP/1.1\r\nHost: www.example.com\r\n\r\n")
data = s.recv(1024)
print(data.decode())
s.close()
- 常用于自定义TCP/UDP协议通信测试
- 适合理解自动化测试中设备网络通信机制
3.6 subprocess子进程管理(自动化测试常用)
3.6.1 常用方法
python复制编辑import subprocess
# 获取命令输出
output = subprocess.check_output(["adb", "devices"], encoding="utf-8")
print(output)
# 实时打印日志(适用于 Monkey 挂测场景)
p = subprocess.Popen("adb logcat", shell=True)
check_output():获取输出结果run():执行命令并返回结果对象Popen():适合长时间运行的任务,支持实时通信
3.7 logging模块:日志输出规范
python复制编辑import logging
logging.basicConfig(
filename="app.log",
level=logging.DEBUG,
format="%(asctime)s - %(levelname)s - %(message)s"
)
logging.info("This is info")
logging.error("This is error")
DEBUG<INFO<WARNING<ERROR<CRITICAL- 可将日志写入文件或控制台,方便调试和记录测试结果
3.8 Python项目打包与部署
3.8.1 使用 PyInstaller 打包 GUI 工具
bash
复制编辑
pyinstaller -F -w your_app.py
-F:打包为单个文件-w:窗口应用,不显示控制台
3.8.2 示例:Monkey挂测工具打包
打包你写的“Monkey多设备挂测工具”,可用于交付和面试作品展示。
3.9 实战建议与面试准备技巧
- 面试项目准备建议:
- 展示清晰的项目目录结构
- 代码应模块化、具备注释、夹具、参数化等
- 具备日志收集、测试报告生成、异常处理机制
- 能打包为可交付工具,如
.exe或.sh
- 面试重点模块:
- pytest 的 fixture/parametrize/xfail 等特性
- requests/Allure/日志/目录结构 等是否规范
- Python 基础是否扎实(文件操作、异常处理、并发)
- 能否独立封装框架,理解设计思路

浙公网安备 33010602011771号