当前位置: 首页 > news >正文

Pytest+requests进行接口自动化测试2.0(yaml)

接口自动化测试学习

  • YAML实战演练(登录接口)
  • 一. 创建yaml文件
    • 1. 创建yaml文件(xxx.yaml)
    • 2. 基本语法
    • 3. 案例练习与讲解(以登录接口为例)
    • 4. PyYAML 库的常用函数
  • 二. yaml文件的读取
    • 1. 导入第三方库。可通过 pip install PyYAML 下载
    • 2. 定义一个接收参数 file(即 YAML 文件的路径)的函数
    • 3. with open 打开指定路径的文件,以 只读模式 ('r') 和 UTF-8 编码 打开
    • 4. try...except 异常处理
      • 1)Exception类异常
      • 2)常用 raise 的异常类型
    • 5. 主程序入口,往函数中传入login.yaml文件
  • 三. yaml文件的写入(指定文件)
    • 1. 封装一个ReadYamlData 类:读取 YAML 文件
      • os模块简单介绍 (os.path 子模块(重要!))
    • 2. 封装一个WriteYamlData 类:写入另一个YAML 文件
    • 3. 主函数运行
      • json序列化和反序列化(重要!!!)
  • 四. yaml文件的使用
    • 1. 从 YAML 文件读取测试用例,并发送 HTTP 请求示例
    • 2. 示例解析
  • 五. yaml测试用例参数动态读取
    • 1. 常见动态参数类型与写法
      • 1)环境变量注入(多环境支持)
      • 2)前置接口依赖提取(extract,常用于获取 token、user_id)
      • 3)函数调用型占位符(最灵活)
      • 4)加密字段动态处理(如 MD5、Base64)
      • 5)变量引用与复用(类似全局变量)
      • 6)数据参数化( 自动生成多条测试用例,每组数据执行一次)
      • 7)条件判断与跳过(高级)
    • 2. 案例:动态参数 token 的替换
      • 1)创建 yaml 接口文档 login.yaml,将 token 设为动态参数
      • 2)将读取的接口返回数据写入指定的 extract.yaml 文件(参考 : 三、yaml文件的写入)
      • 3)从 extract.yaml 读取接口返回数据的变量值 value
      • 4)创建 debugtalk.py 文件,读取特定的变量值 value 并自定义(举例:password 的 value 为列表)
      • 5)替换 login.yaml 中的动态参数 token

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- data2test_case:         # 嵌套字典写法case1: 有效登录case2: 无效登录test: {name: liu,age: 18}  # 内联写法long_str: >        # 多行字符串写法这是一段换行的文字

3. 案例练习与讲解(以登录接口为例)

- baseInfo:api_name: 用户登录url: /dar/user/login    --- 这里是相对路径,通常会拼接 base_urlmethod: Postheader:Content-Type: application/x-www-form-urlencoded;charset=UTF-8test_case:- case_name: 用户名和密码正确登录验证data:                     ---  根据请求头设置data,jsonuser_name: test01password: admin123validation:- eq: [msg, 登录成功]extract:           --- 从响应 JSON 中提取 token 字段,保存为变量 tokentoken: $.token   --- JSONPath 语法,表示根节点下的 token 字段- case_name: 用户名和密码错误登录验证data:                  user_name: test0123password: admin123validation:- 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 字段,保存为变量 tokentoken: $.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 yamldef 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_dateexcept Exception as e:raise eif __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 eraise 是 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 yamlclass ReadYamlData:"""读取 YAML 数据"""def __init__(self, yaml_file='login.yaml'):self.yaml_file = yaml_filedef 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() 拼接路径保证跨平台兼容
使用 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, …)安全拼接路径
os.path.basename(path)获取文件名(如 ‘file.txt’)
os.path.dirname(path)获取目录部分,例如:dirname(‘output/data.yaml’) → ‘output’
os.path.splitext(path)分离文件名和扩展名

2. 封装一个WriteYamlData 类:写入另一个YAML 文件

  • 整体展示
class WriteYamlData:"""写入 YAML 数据"""def __init__(self, yaml_file='extract.yaml'):self.yaml_file = yaml_filedef 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' + urldata = 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.posttoken = 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/loginmethod: Postheader:Content-Type: application/x-www-form-urlencoded;charset=UTF-8test_case:- case_name: 用户名和密码正确登录验证data:                     # 根据请求头设置data,jsonuser_name: test01password: admin123validation:- 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_dataexcept 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   ---- 拼接成完整URLmethod = 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: 登录获取 tokenextract:token: $.data.token        # 使用 JSONPath 提取user_id: $.data.user.id
  • 后续测试用例中引用
- case_name: 获取用户信息request:method: GETurl: /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}}"        --- 明文自动 MD5data: "{{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: /loginmethod: POSTjson:username: "{user_info[0]}"password: "{user_info[1]}"

7)条件判断与跳过(高级)

- name: 只有登录成功才执行request:url: /delete/userskip_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.tokenJSONPath 提取

2. 案例:动态参数 token 的替换

{{get_data(TOKEN)}} 类型的动态参数均可使用(支持同一yaml文档多个)

1)创建 yaml 接口文档 login.yaml,将 token 设为动态参数

    header:Content-Type: application/jsonTOKEN: "{{get_data(TOKEN)}}"

2)将读取的接口返回数据写入指定的 extract.yaml 文件(参考 : 三、yaml文件的写入)

class WriteYamlData:"""写入 YAML 数据"""def __init__(self, yaml_file='extract.yaml'):self.yaml_file = yaml_filedef 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_filedef 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 Nonewith 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_datasif __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 jsonclass BaseRequest:def __init__(self):self.read = ReadYamlData()def replace_load(self,data):"""yaml文件替换解析有{{ }}格式的数据"""str_data = dataif not isinstance(data,str):str_data = json.dumps(data,ensure_ascii=False)print('yaml文件替换解析前',str_data)start = 0while True:s = str_data.find('{{', start)   # 从str_data第 0 个位置开始找if s == -1: breakb = str_data.find('(', s)       # 从str_data第 s 个位置开始找 (if b == -1: breake = str_data.find(')', b)       # 从str_data第 b 个位置开始找 )if e == -1: breakfunc_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)continueif data and isinstance(data,dict):data = json.loads(str_data)else:data = str_datareturn dataif __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 = dataif not isinstance(data,str):str_data = json.dumps(data,ensure_ascii=False)   print('yaml文件替换解析前',str_data)

循环查找 {{ func(…) }} 取出函数名 get_data,参数 TOKEN ,和需替换的内容

 start = 0while True:s = str_data.find('{{', start)   # 从str_data第 0 个位置开始找if s == -1: breakb = str_data.find('(', s)       # 从str_data第 s 个位置开始找 (if b == -1: breake = str_data.find(')', b)       # 从str_data第 b 个位置开始找 )if e == -1: breakfunc_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_datareturn data

在这里插入图片描述


文章转载自:

http://CoiTln7I.rqjxc.cn
http://WiyUiOBr.rqjxc.cn
http://eaUrly6K.rqjxc.cn
http://aAaiMiay.rqjxc.cn
http://8grdL7Uh.rqjxc.cn
http://Nz79GeJ5.rqjxc.cn
http://1KIHpQTc.rqjxc.cn
http://ysaclHFd.rqjxc.cn
http://wEsrv5b7.rqjxc.cn
http://jV6Q0ZOt.rqjxc.cn
http://VlvjIP72.rqjxc.cn
http://eTGhmQdX.rqjxc.cn
http://4L27zrBT.rqjxc.cn
http://t7ZdhCeE.rqjxc.cn
http://SDLm976w.rqjxc.cn
http://DYWOIrV1.rqjxc.cn
http://XPFZ6SNw.rqjxc.cn
http://dBFPdcmk.rqjxc.cn
http://HlLCAevv.rqjxc.cn
http://Aw75waD4.rqjxc.cn
http://wvnRuuC9.rqjxc.cn
http://WKLWh3nq.rqjxc.cn
http://7stv8pBQ.rqjxc.cn
http://ZlPM0Q73.rqjxc.cn
http://565gXTIq.rqjxc.cn
http://l2GL4NRr.rqjxc.cn
http://wjgZPIJG.rqjxc.cn
http://mV1bZALs.rqjxc.cn
http://8Zwoo4Id.rqjxc.cn
http://KrZlqdxw.rqjxc.cn
http://www.dtcms.com/a/378563.html

相关文章:

  • 【容器使用】如何使用 docker 和 tar 命令来操作容器镜像
  • 科普:在Windows个人电脑上使用Docker的极简指南
  • 【面试场景题】电商订单系统分库分表方案设计
  • 微服务保护全攻略:从雪崩到 Sentinel 实战
  • springcloud二-Sentinel
  • Redis 持久化与高可用实践(RDB / AOF / Sentinel / Cluster 全解析)
  • Semaphore 信号量深度解析
  • 门店网络重构:告别“打补丁”,用“云网融合”重塑数字竞争力!
  • Linux操作系统之Ubuntu
  • WSL自定义安装多个相同版本的Ubuntu子系统
  • 晶振在5G时代的角色:高精度时钟的核心支撑
  • 【JavaEE】(25) Spring 原理
  • 【科研绘图系列】R语言绘制模型预测与数据可视化
  • 音频中的PDM、PCM概念解读
  • 离线应用开发:Service Worker 与缓存
  • 1、RocketMQ概念详解
  • ZooKeeper Multi-op+乐观锁实战优化:提升分布式Worker节点状态一致性
  • 使用yolo算法对视频进行实时目标跟踪和分割
  • Tomcat日志乱码了怎么处理?
  • 新手该选哪款软件?3ds Max vs Blender深度对比
  • 剧本杀小程序系统开发:构建线上线下融合的剧本杀生态圈
  • 常用加密算法之 AES 简介及应用
  • 【SQL注入系列】JSON注入
  • 盲盒抽卡机小程序:从0到1的蜕变之路
  • 设计模式(C++)详解—工厂方法模式(1)
  • 【Proteus仿真】【51单片机】教室灯光控制器设计
  • java语言中,list<String>转成字符串,逗号分割;List<Integer>转字符串,逗号分割
  • Jenkins运维之路(Jenkins流水线改造Day01)
  • 9月11日星期四今日早报简报微语报早读
  • 阿里兵临城下,美团迎来至暗时刻?