接口自动化测试学习
YAML实战演练(登录接口)
YAML 是一种用来 存储和传输结构化数据 的文件格式,常用于配置文件、测试用例、项目设置等
一. 创建yaml文件
1. 创建yaml文件(xxx.yaml)

2. 基本语法
介绍 YAML 的基本语法,如键值对、列表、嵌套结构等
| 写法 | 含义 |
|---|---|
| key: value | 键值对(注意冒号后有空格) |
| # 这是注释 | 注释 |
| list: - item1 - item2 | 列表 |
| dict: name: 张三 age: 25 | 字典 |
| data: {name: 张三, age: 25} | 内联写法 |
| long_str: > 这是一段 换行的文字 | 多行字符串 |
- 示例代码(基本语法)
api_name: 登录接口 # 键值对写法
# 注释
test2: # 列表写法
- data1
- data2
test_case: # 嵌套字典写法
case1: 有效登录
case2: 无效登录
test: {name: liu,age: 18} # 内联写法
long_str: > # 多行字符串写法
这是一段
换行的文字
3. 案例练习与讲解(以登录接口为例)
- baseInfo:
api_name: 用户登录
url: /dar/user/login --- 这里是相对路径,通常会拼接 base_url
method: Post
header:
Content-Type: application/x-www-form-urlencoded;charset=UTF-8
test_case:
- case_name: 用户名和密码正确登录验证
data: --- 根据请求头设置data,json
user_name: test01
password: admin123
validation:
- eq: [msg, 登录成功]
extract: --- 从响应 JSON 中提取 token 字段,保存为变量 token
token: $.token --- JSONPath 语法,表示根节点下的 token 字段
- case_name: 用户名和密码错误登录验证
data:
user_name: test0123
password: admin123
validation:
- eq: [msg, 登录成功] --- 自动化框架会解析这个 validation,自动验证
extract:
token: $.token
- 开头的短横线:设计成列表是为了以后可以添加多个接口
- baseInfo: { ... } # 登录
- baseInfo: { ... } # 获取用户信息
- test_case:这个接口的多个测试用例
test_case:
- case_name: ...
- case_name: ...
- validation:断言(验证响应是否符合预期)
validation:
- eq: [msg, 登录成功] --- 自动化框架会解析这个 validation,自动验证
- extract:从响应中提取变量(用于后续接口调用)
extract: --- 从响应 JSON 中提取 token 字段,保存为变量 token
token: $.token --- JSONPath 语法,表示根节点下的 token 字段
4. PyYAML 库的常用函数
| 函数 | 用途 |
|---|---|
| yaml.safe_load() ,yaml.safe_load_all() | 读取单个 (多个) YAML 文档 |
| yaml.dump(),yaml.dump_all() | 写入单个 (多个) YAML 文档 |
| yaml.add_representer() | 高级用法:自定义序列化 |
二. yaml文件的读取
- 读取yaml文件,并将其转换为python可解析的内容
import yaml
def get_testcase_yaml(file):
"""
获取yaml文件的数据
:param file: yaml文件的路径
:return: 返回读取到的yaml文件
"""
try:
with open(file, 'r', encoding='utf-8') as f:
yaml_date = yaml.safe_load(f)
return yaml_date
except Exception as e:
raise e
if __name__ == '__main__':
res = get_testcase_yaml('login.yaml')
print(res)

- 语法逐个解释
1. 导入第三方库。可通过 pip install PyYAML 下载
import yaml
2. 定义一个接收参数 file(即 YAML 文件的路径)的函数
def get_testcase_yaml(file):
"""
获取yaml文件的数据(获取测试用例的 YAML 数据)
:param file: yaml文件的路径
:return: 返回读取到的yaml文件
"""
可以用于多个 YAML 文件的读取
3. with open 打开指定路径的文件,以 只读模式 (‘r’) 和 UTF-8 编码 打开
使用 with 的好处: 自动关闭文件,即使发生异常也不会造成资源泄漏
with open(file, 'r', encoding='utf-8') as f:
yaml_date = yaml.safe_load(f)
return yaml_date
- yaml.safe_load( f ) 将打开的文件对象 f 安全解析成 Python 的数据结构(如字典、列表等)
- return yaml_date 把解析后的数据返回出去,供后续使用(比如执行测试用例)
4. try…except 异常处理
使用 try…except,如果文件路径错了或内容非法,程序不会报错退出,而是打印错误信息并继续运行
try:
...
except Exception as e:
raise e
| 代码部分 | 含义 |
|---|---|
| except | 当 try 块中出现异常时,就跳到这里处理 |
| Exception | 捕获所有继承自 Exception 的异常(即绝大多数常见错误) |
| as e | 把异常对象保存到变量 e 中,方便查看具体错误信息 |
| raise e | raise 是 Python 中的一个关键字,作用是 “主动抛出一个异常” |
1)Exception类异常
Exception 是一个“父类”,它能捕获几乎所有你常见的、程序运行时出错的情况
如果想要精细化 Exception 异常处理,可以捕获具体的异常(生产环境)
- 示例:
try:
with open(file, 'r', encoding='utf-8') as f:
return yaml.safe_load(f)
except FileNotFoundError:
print(f"文件未找到: {file}")
except yaml.YAMLError as e:
print(f"YAML解析错误: {e}")
except PermissionError:
print(f"没有权限读取文件: {file}")
except Exception as e:
print(f"未知错误: {e}")
return None
2)常用 raise 的异常类型
| 异常类型 | 适用场景 |
|---|---|
| ValueError | 值不合适,如年龄为负数 |
| TypeError | 类型错误,如传了字符串要当数字用 |
| FileNotFoundError | 文件不存在 |
| KeyError | 字典中找不到某个键 |
| PermissionError | 没有权限访问文件或目录 |
| Exception | 通用异常(不推荐滥用) |
5. 主程序入口,往函数中传入login.yaml文件
if __name__ == '__main__':
res = get_testcase_yaml('login.yaml')
print(res)
三. yaml文件的写入(指定文件)
将读取的接口数据写入指定的 yaml 文件
- 把写入拆分为读取 + 写入
1. 封装一个ReadYamlData 类:读取 YAML 文件
- 整体展示
import os
import yaml
class ReadYamlData:
"""读取 YAML 数据"""
def __init__(self, yaml_file='login.yaml'):
self.yaml_file = yaml_file
def read(self):
"""读取 YAML 文件并返回字典"""
if not os.path.exists(self.yaml_file):
raise FileNotFoundError(f"配置文件不存在: {self.yaml_file}")
with open(self.yaml_file, 'r', encoding='utf-8') as f:
try:
return yaml.safe_load(f) or {}
except yaml.YAMLError as e:
raise ValueError(f"YAML 解析错误: {e}")
- 解释分析
class ReadYamlData:
"""读取 YAML 数据"""
def __init__(self, yaml_file='login.yaml'):
self.yaml_file = yaml_file
- 定义了一个类 ReadYamlData,用于封装读取 YAML 文件的功能。
- 构造函数接受一个可选参数 yaml_file,默认值为 ‘login.yaml’,表示如果调用时不传路径,则默认读取当前目录下的 login.yaml 文件。
- 将文件名保存在实例变量 self.yaml_file 中,供后续方法使用。
def read(self):
"""读取 YAML 文件并返回字典"""
if not os.path.exists(self.yaml_file):
raise FileNotFoundError(f"配置文件不存在: {self.yaml_file}")
with open(self.yaml_file, 'r', encoding='utf-8') as f:
try:
return yaml.safe_load(f) or {}
except yaml.YAMLError as e:
raise ValueError(f"YAML 解析错误: {e}")
- 使用 os.path.exists() 检查文件是否存在
- return xx or {}:如果文件为空或解析结果为 None,返回空字典 {},避免返回 None 导致后续 KeyError。
os模块简单介绍 (os.path 子模块(重要!))
os 是 Python 的标准库模块之一,全称是 “Operating System”(操作系统)。它提供了与操作系统进行交互的接口,掌握它就等于掌握了文件系统操作的基本能力
| 总结模块使用要点 | 说明 |
|---|---|
| 使用 os.path.join() 拼接系统路径 | 保证跨平台兼容(不能用于拼接URL) |
| 使用 os.path.exists() 判断文件前先检查 | 避免 FileNotFoundError |
| 优先使用 os.makedirs(…, exist_ok=True) | 安全创建多级目录 |
| 读写文件时配合 encoding=‘utf-8’ | 支持中文 |
| 避免直接拼接路径字符串 | 如 ‘folder\file.txt’ 易出错 |
os.path 是 os 模块中专门处理路径的子模块,非常常用:
| 函数 | 作用 |
|---|---|
| os.path.exists(path) | 路径是否存在 |
| os.path.isfile(path) | 是否是文件 |
| os.path.isdir(path) | 是否是目录 |
| os.path.join(a, b, …) | 安全拼接当前系统路径(不能用于拼接URL) |
| os.path.basename(path) | 获取文件名(如 ‘file.txt’) |
| os.path.dirname(path) | 获取目录部分,例如:dirname(‘output/data.yaml’) → ‘output’ |
| os.path.splitext(path) | 分离文件名和扩展名 |
(注:URL拼接可使用urljoin)
from urllib.parse import urljoin
url = urljoin(f"{base_url}",case_info['baseInfo']['url'])
2. 封装一个WriteYamlData 类:写入另一个YAML 文件
- 整体展示
class WriteYamlData:
"""写入 YAML 数据"""
def __init__(self, yaml_file='extract.yaml'):
self.yaml_file = yaml_file
def write(self, data):
"""
写入数据到 YAML 文件(覆盖模式)
:param data: dict 类型数据
"""
if not isinstance(data, dict):
raise TypeError("写入的数据必须是字典类型")
# 确保目录存在(如果路径含子目录)
parent_dir = os.path.dirname(self.yaml_file)
if parent_dir and not os.path.exists(parent_dir):
os.makedirs(parent_dir)
# 写入文件(覆盖原内容)
with open(self.yaml_file, 'w', encoding='utf-8') as f:
yaml.dump(data, f, allow_unicode=True, sort_keys=False, default_flow_style=False)
- 解释分析
class WriteYamlData:
"""写入 YAML 数据"""
def __init__(self, yaml_file='extract.yaml'):
self.yaml_file = yaml_file
- yaml_file=‘extract.yaml’:设置默认参数,若不指定文件名,则默认写入 extract.yaml文件(不会自动创建文件)
def write(self, data):
"""
写入数据到 YAML 文件(覆盖模式)
:param data: dict 类型数据
"""
if not isinstance(data, dict):
raise TypeError("写入的数据必须是字典类型")
isinstance(obj, type):判断 obj 是否是某个类型(这里是 dict)
parent_dir = os.path.dirname(self.yaml_file)
if parent_dir and not os.path.exists(parent_dir):
os.makedirs(parent_dir)
- os.path.dirname(获取路径) 和 os.makedirs(创建路径) —— 确保你要写入的 YAML 文件所在的目录存在,如果不存在,就自动创建它
- if parent_dir:防止根目录或当前目录(如 ‘’)被误判
with open(self.yaml_file, 'w', encoding='utf-8') as f:
yaml.dump(data, f, allow_unicode=True, sort_keys=False, default_flow_style=False)
- with open(…, ‘w’, encoding=‘utf-8’) as f: —— 安全写入文件('w’为覆盖 'a’为底部追加)
- yaml.dump(…) —— 序列化为 YAML 格式
3. 主函数运行
从 YAML 文件读取登录接口的测试数据 → 发送登录请求 → 提取返回的 token → 把 token 写入另一个 YAML 文件供后续使用
调用ReadYamlData()类中的read方法,解析‘login.yaml’文件,在解析好的数据中获得url,data,header
if __name__ == '__main__':
read_yaml = ReadYamlData()
res = read_yaml.read()[0]
url = res['baseInfo']['url']
new_url = 'http://192.168.4.200' + url
data = res['test_case'][0]['json']
header = res['baseInfo']['header'] ------ 拆分yaml文件
发送post接口请求,并拿到返回数据中的 token (注: 返回的对象需用 .json()转换为json格式)
resp = requests.post(url=new_url, json=data, headers=header) ----- 调用requests.post
token = resp.json()['data']['token'] ------ 获取接口返回数据中的token
创建一个字典,把提取到的 token 存进去,准备写入文件
write_date = {} ------ 创建write_date,将获取到的token传入
write_date['TOKEN'] = token
调用WriteYamlData() 类中的write方法,把 {‘TOKEN’: ‘xxx’} 写入 extract.yaml 文件
read_data = WriteYamlData()
read_data.write(write_data) # 传入字典类型
- 生成结果

json序列化和反序列化(重要!!!)
| 方法 | 输入类型 | 输出类型 | 用途 |
|---|---|---|---|
| json.loads(str) | 字符串 | 字典(dict) | 反序列化:字符串 → 字典 |
| json.dumps(dict) | 字典 | 字符串 | 序列化:字典 → 字符串 |
json序列化,其实就是将python的宇典类型转换为字符串类型
- (ensure_ascii=False 让中文正常显示)
json_str = json.dumps(resp,ensure_ascii=False)
print(json_str)
print(type(json_str))
json反序列化,其实就是将宇符串类型转换为字典类型
json_dict = json.loads(json_str)
print(json_dict)
print(type(json_dict))
四. yaml文件的使用
- 前置条件,yaml文件内容
- baseInfo:
api_name: 用户登录
url: /dar/user/login
method: Post
header:
Content-Type: application/x-www-form-urlencoded;charset=UTF-8
test_case:
- case_name: 用户名和密码正确登录验证
data: # 根据请求头设置data,json
user_name: test01
password: admin123
validation:
- eq: [msg, 登录成功]
extract:
token: $.token
- 封装了 requests 库的模块 sendrequests.py

1. 从 YAML 文件读取测试用例,并发送 HTTP 请求示例
import yaml
def run_yaml(file):
try:
with open(file, 'r', encoding='utf-8') as f:
yaml_data = yaml.safe_load(f)
return yaml_data
except Exception as e:
print(e)
if __name__ == '__main__':
res = run_yaml('login.yaml')[0] # 读取YAML中的第一个测试用例
url = res['baseInfo']['url'] # 获取原始URL路径
new_url = 'http://127.0.0.1:8787' + url ---- 拼接成完整URL
method = res['baseInfo']['method'] # 获取请求方法(如POST)
data = res['test_case'][0]['data'] # 获取第一组测试数据
header = res['baseInfo']['header'] # 获取请求头
from sendrequests import SendRequest ---- 导入自定义请求类
send = SendRequest() # 创建请求对象
result = send.run_main(method=method, url=new_url, data=data, header=header) # 发送请求
print(result) # 打印响应结果
2. 示例解析
- res = run_yaml(‘login.yaml’)[0]
调用一个叫 run_yaml 的函数,读取 login.yaml 文件,run_yaml() 返回的是一个列表,读取该列表的第一个用例
- url = res[‘baseInfo’][‘url’]
字典形式的数据读取方式
五. yaml测试用例参数动态读取
- 为什么要进行参数动态读取 ?
(热加载)在接口测试中,某些参数不能写死,需要通过动态解析实现参数值的替换。如:不同的环境配置, token、时间戳、随机数、加密字段
1. 常见动态参数类型与写法
1)环境变量注入(多环境支持)
- 前置条件数据
# config/test.yaml
env: test
base_url: http://test.api.com
db_host: 192.168.10.20
# config/prod.yaml
env: prod
base_url: https://api.company.com
db_host: 10.10.10.100
- 后续测试用例中引用
- case_name: 用户登录
url: "{{ENV:base_url}}/login"
2)前置接口依赖提取(extract,常用于获取 token、user_id)
- 前置条件数据
- case_name: 登录获取 token
extract:
token: $.data.token # 使用 JSONPath 提取
user_id: $.data.user.id
- 后续测试用例中引用
- case_name: 获取用户信息
request:
method: GET
url: /user/{{token}}
headers:
Authorization: "Bearer {{token}}"
3)函数调用型占位符(最灵活)
支持自定义函数:UUID()、timestamp()、random_phone()、md5(str) 等
- case_name: 创建订单
json:
order_no: "{{UUID}}" --- 生成唯一订单号
timestamp: "{{TIMESTAMP}}" --- 当前时间戳
phone: "{{RANDOM_PHONE}}" --- 随机手机号
email: "{{RANDOM_EMAIL}}" --- 随机邮箱
sign: "{{MD5:{{timestamp}}key}}" --- 动态签名(支持嵌套)
4)加密字段动态处理(如 MD5、Base64)
- 简单版(直接加密)
json:
password: "{{md5:123456}}" --- 明文自动 MD5
data: "{{base64:hello world}}" --- `在这里插入代码片`Base64 编码
- 复杂版(引用变量 + 加密)
json:
password: "{{sha256:{{PWD}}}}" --- 引用变量 + 加密
5)变量引用与复用(类似全局变量)
test_cases:
- name: 登录
request:
url: "{{api_prefix}}/login"
json:
user_name: "{{username}}"
password: "{{md5:{{PWD}}}"
6)数据参数化( 自动生成多条测试用例,每组数据执行一次)
- name: 多组登录测试
parameters:
user_info:
- ["admin", "123456"]
- ["guest", "guest123"]
- ["invalid", "wrong"]
request:
url: /login
method: POST
json:
username: "{user_info[0]}"
password: "{user_info[1]}"
7)条件判断与跳过(高级)
- name: 只有登录成功才执行
request:
url: /delete/user
skip_if:
condition: "{{token}}" is null # 如果 token 为空则跳过
reason: "未登录,跳过删除操作"
- 总结
| 写法 | 示例 | 用途 |
|---|---|---|
| {{var}} | {{token}} | 引用变量 |
| {{ENV:key}} | {{ENV:base_url}} | 环境变量 |
| {{func:arg}} | {{md5:123}} | 函数处理 |
| {param} | {user_id} | 参数化 |
| $var | $token | 简写(部分框架) |
| $.json.path | $.data.token | JSONPath 提取 |
2. 案例:动态参数 token 的替换
{{get_data(TOKEN)}} 类型的动态参数均可使用(支持同一yaml文档多个)
1)创建 yaml 接口文档 login.yaml,将 token 设为动态参数
header:
Content-Type: application/json
TOKEN: "{{get_data(TOKEN)}}"
2)将读取的接口返回数据写入指定的 extract.yaml 文件(参考 : 三、yaml文件的写入)
class WriteYamlData:
"""写入 YAML 数据"""
def __init__(self, yaml_file='extract.yaml'):
self.yaml_file = yaml_file
def write(self, data):
"""
写入数据到 YAML 文件(覆盖模式)
:param data: dict 类型数据
"""
if not isinstance(data, dict):
raise TypeError("写入的数据必须是字典类型")
# 确保目录存在(如果路径含子目录)
parent_dir = os.path.dirname(self.yaml_file)
if parent_dir and not os.path.exists(parent_dir):
os.makedirs(parent_dir)
# 写入文件(覆盖原内容)
with open(self.yaml_file, 'w', encoding='utf-8') as f:
yaml.dump(data, f, allow_unicode=True, sort_keys=False, default_flow_style=False)

3)从 extract.yaml 读取接口返回数据的变量值 value
读取extract.yaml文件数据 - - - > 如果没有extract.yaml文件,则创建空文件返回None,如果有extract.yaml文件直接读取传入 key(node_name) 的变量值 value
class GetExtractData:
"""读取接口提取的变量值"""
def __init__(self, yaml_file='extract.yaml'):
self.yaml_file = yaml_file
def get_extract_data(self,node_name):
"""
获取extract.yaml文件的数据
:param node_name: extract.yaml文件中的key值
:return:
"""
if not os.path.exists(self.yaml_file): --- 如果不存在extract.yaml,创建空文件
print(f'{self.yaml_file}不存在,正在创建...')
with open(self.yaml_file, 'w', encoding='utf-8') as f:
yaml.dump({}, f, allow_unicode=True, sort_keys=False, default_flow_style=False)
return None
with open(self.yaml_file, 'r', encoding='utf-8') as rf:
open_data = yaml.safe_load(rf)
return open_data.get(node_name)

4)创建 debugtalk.py 文件,读取特定的变量值 value 并自定义(举例:password 的 value 为列表)
自动化测试框架中的 debugtalk.py 文件,用于在 YAML 测试用例中调用自定义函数(如动态参数、加密、数据提取等)
- 整体展示
实现从 extract.yaml 文件中读取之前接口提取的变量(如 token、password等),并支持多种读取方式:
- 直接获取
- 随机取一个
- 取第 N 个
- 拼接成字符串等
class DebugTalk:
def __init__(self):
self.extract_data = GetExtractData()
def get_extract_order_data(self,data,randoms):
if randoms not in [0,-1,-2]:
return data[randoms - 1]
def get_data(self,node_name,randoms=None):
"""
获取 extract.yaml 中的数据,支持多种读取方式
:param node_name: 键名,如 'TOKEN'
:param randoms: 控制读取方式
None: 原样返回
1,2,3...: 返回第 N 个(从1开始)
0: 随机一个
-1: 拼接成字符串
:return:
"""
token_datas = self.extract_data.get_extract_data(node_name)
if randoms is not None:
intrandoms = int(randoms)
data_value = {
randoms :self.get_extract_order_data(token_datas,randoms),
0 : random.choice(token_datas), # random.choice从数组里面随机读取
-1 : ''.join(token_datas), # 拼接字符串
-2 : ','.join(token_datas).split(',') # 转换为数组
}
token_datas = data_value[intrandoms]
return token_datas
if __name__ == '__main__':
debug_talk = DebugTalk()
print(debug_talk.get_data('TOKEN'))
print(debug_talk.get_data('password',3))

- 代码详解
创建一个可以被 YAML 测试用例调用的“工具类”。使用了上面的 3)GetExtractData 来读数据。
class DebugTalk:
def __init__(self):
self.extract_data = GetExtractData()
若数据为列表,且传入的randoms不为0,-1,-2,则取 data[randoms - 1] (假如传入3,则取索引为2的数据,这里没有设置边界值)
def get_extract_order_data(self,data,randoms):
if randoms not in [0,-1,-2]:
return data[randoms - 1]
通过 GetExtractData().get_extract_data 从 extract.yaml 中拿到数据
def get_data(self,node_name,randoms=None):
token_datas = self.extract_data.get_extract_data(node_name)
判断取得的数据是否需要特殊处理(randoms 不为空)randoms为空不需要处理
- 根据 randoms 的值选择不同的返回方式:
None: 原样返回
1,2,3…: 返回第 N 个(调用get_extract_order_data,从索引0开始)
0: 随机一个
-1: 拼接成字符串
-2:转换为数组
if randoms is not None:
intrandoms = int(randoms)
data_value = {
randoms :self.get_extract_order_data(token_datas,randoms),
0 : random.choice(token_datas), # random.choice从数组里面随机读取
-1 : ''.join(token_datas), # 拼接字符串
-2 : ','.join(token_datas).split(',') # 转换为数组
}
token_datas = data_value[intrandoms]
return token_datas
调用DebugTalk类里的 get_data 方法,打印我们需要的数据
if __name__ == '__main__':
debug_talk = DebugTalk()
print(debug_talk.get_data('TOKEN'))
print(debug_talk.get_data('password',3))

5)替换 login.yaml 中的动态参数 token
- 整体展示
在自动化测试框架中解析并替换类似 {{ func_name(param) }} 格式的表达式
from run_yaml import ReadYamlData
from debugtalk import DebugTalk
import json
class BaseRequest:
def __init__(self):
self.read = ReadYamlData()
def replace_load(self,data):
"""yaml文件替换解析有{{ }}格式的数据"""
str_data = data
if not isinstance(data,str):
str_data = json.dumps(data,ensure_ascii=False)
print('yaml文件替换解析前',str_data)
start = 0
while True:
s = str_data.find('{{', start) # 从str_data第 0 个位置开始找
if s == -1: break
b = str_data.find('(', s) # 从str_data第 s 个位置开始找 (
if b == -1: break
e = str_data.find(')', b) # 从str_data第 b 个位置开始找 )
if e == -1: break
func_name = str_data[s+2:b] # 取出函数名, s 为{{get_data(TOKEN)}}第一个{的位置
func_params = str_data[b+1:e] # 取出参数名, b 为{{get_data(TOKEN)}}第一个( 的位置
func_all = str_data[s:e + 3] # 全部需替换内容
extract_data = getattr(DebugTalk(),func_name)(*func_params.split(',') if func_params else "")
str_data = str_data.replace(func_all,extract_data)
print('yaml文件替换解析后',str_data)
continue
if data and isinstance(data,dict):
data = json.loads(str_data)
else:
data = str_data
return data
if __name__ == '__main__':
data = ReadYamlData().read()[0]
base = BaseRequest()
base.replace_load(data)

- 解析说明
- ReadYamlData: 用于读取 login.yaml 数据(参考 : 三、yaml文件的写入)
- 调用 debugtalk.py 文件中的 DebugTalk 类
from run_yaml import ReadYamlData
from debugtalk import DebugTalk
import json
核心方法:replace_load(data)
- 该方法负责查找并替换数据中所有形如 {{ func_name(param) }} 的表达式。
- json.dumps(data,ensure_ascii=False) 将数据全转换为字符串类型,方便后续用字符串方法 find 查找 {{ }}
class BaseRequest:
def __init__(self):
self.read = ReadYamlData()
def replace_load(self,data):
"""yaml文件替换解析有{{ }}格式的数据"""
str_data = data
if not isinstance(data,str):
str_data = json.dumps(data,ensure_ascii=False)
print('yaml文件替换解析前',str_data)
循环查找 {{ func(…) }} 取出函数名 get_data,参数 TOKEN ,和需替换的内容
start = 0
while True:
s = str_data.find('{{', start) # 从str_data第 0 个位置开始找
if s == -1: break
b = str_data.find('(', s) # 从str_data第 s 个位置开始找 (
if b == -1: break
e = str_data.find(')', b) # 从str_data第 b 个位置开始找 )
if e == -1: break
func_name = str_data[s+2:b] # 取出函数名, s 为{{get_data(TOKEN)}}第一个{的位置
func_params = str_data[b+1:e] # 取出参数名, b 为{{get_data(TOKEN)}}第一个( 的位置
func_all = str_data[s:e + 3] # 全部需替换内容
动态调用 DebugTalk 中的函数获取token值,替换并更新字符串
- getattr(DebugTalk(), func_name) 获取 DebugTalk 类中名为 func_name 的方法。
- func_params.split(‘,’) 将参数按逗号分割成列表。
- ( * ) 解包参数传给函数执行,如果无参数,则传空字符串。
extract_data = getattr(DebugTalk(),func_name)(*func_params.split(',') if func_params else "")
str_data = str_data.replace(func_all,extract_data)
print('yaml文件替换解析后',str_data)
continue
最后:还原数据类型
- 如果原始输入是字典,则尝试把最终字符串再转回字典,否则直接返回字符串
if data and isinstance(data,dict):
data = json.loads(str_data)
else:
data = str_data
return data

1112

被折叠的 条评论
为什么被折叠?



