pytest之fixture中yield详解

1. fixture——yield介绍

fixture的teardown操作并不是独立的函数,用yield关键字呼唤teardown操作。前面通过fixture实现了在每个用例之前执行初始化操作,那么用例执行完之后,如需要清除数据(或还原)操作,可以使用yield来实现。

yield是一个关键字,它不是单独存在的,要写在fixture标记的固件中。我们在声明的固件fixture中加入yield关键字,在它下面写测试用例执行后想要运行的代码;其他有关于固件的使用没有任何差别。需要说明的一点是我们在pytest主函数中增加一个参数-setup-show,它会显示出固件的执行情况。

自动执行清理逻辑:无论测试是否通过、是否抛出异常,yield后的代码始终会被执行。这确保资源(如文件、网络连接)被正确释放。但是如果固件中的yield之前的代码也是相当于setup部分的代码,出现错误或断言失败,那么yield后的代码将不会再执行,当然测试用例中的代码也不会执行。

2. 基本原理:通过 yield 分割执行阶段

在 fixture 函数中,yield语句将代码分为两部分:

  • 前置操作yield之前的代码在测试执行前运行(类似于 setup)。
  • 返回值yield后的值作为 fixture 的返回值传递给测试函数。
  • 后置操作yield之后的代码在测试执行后运行(类似于 teardown),无论测试是否通过。

用法示例

#!/usr/bin/env python
# encoding: utf-8
'''
@Author  : 草木零
@Software: PyCharm
@File    : test_yield.py
@Time    : 2023/8/23 0:50
@desc   : fixture装饰的函数里,yield的代码,是pytest用例执行完后再执行的
'''
import pytest@pytest.fixture
def fix1():print('\nfix1,用例前置')yieldprint('\nfix1,用例执行完成,收尾')# 测试用例
def test_yield(fix1):print('fixture + yield的测试用例')if __name__ == '__main__':pytest.main(['-s', 'test_yield.py'])

控制台:
在这里插入图片描述

3. 处理异常的清理

yield前的代码抛出异常,yield后的清理代码不会执行。需使用try/finally包裹:

@pytest.fixture
def safe_setup():resource = Nonetry:resource = acquire_resource()  # 可能抛出异常yield resourcefinally:if resource:resource.release()  # 确保资源被释放

4. yield详解

在 Python 中,yield是创建生成器(Generator)的核心关键字。生成器是一种特殊的迭代器,它允许你在迭代过程中动态生成值,而不是一次性生成所有值。这种特性让生成器在处理大数据、优化内存和实现异步编程时非常有用。

yield: return 
yield: return + generator 的一部分
PS:带yield的函数才是完整的generator 

(1) 生成器的本质:按需生成的迭代器

生成器是 Python 中实现惰性计算的主要方式,它有两种形式:

a. 生成器函数(Generator Function)
使用yield关键字的函数,调用时返回一个生成器对象:

def count_up_to(n):i = 0while i <= n:yield i  # 暂停执行并返回当前值i += 1# 创建生成器对象(不会立即执行函数体)
gen = count_up_to(3)# 通过迭代获取值
print(next(gen))  # 输出: 0
print(next(gen))  # 输出: 1
print(next(gen))  # 输出: 2
print(next(gen))  # 输出: 3
print(next(gen))  # 抛出 StopIteration 异常

b. 生成器表达式(Generator Expression)
类似列表推导式,但使用圆括号:

gen = (x**2 for x in range(3))  # 创建生成器print(next(gen))  # 输出: 0
print(next(gen))  # 输出: 1
print(next(gen))  # 输出: 4

(2) yield 的核心作用:暂停与恢复执行

当生成器函数被调用时,函数体不会立即执行,而是返回一个生成器对象。每次调用next()时:

  • 生成器从上次暂停的位置继续执行(或从函数起始处开始)。
  • 执行到yield语句时,生成一个值并暂停执行。
  • 下一次调用next()时,继续执行yield之后的代码。

总结:yield和return的关系和区别

yield的函数是一个生成器,而不是一个函数了。这个生成器有一个函数就是next函数,next就相当于“下一步”生成哪个数,这一次的next开始的地方是接着上一次的next停止的地方执行的。所以调用next的时候,生成器并不会从yield_demo函数的开始执行,而是接着上一步开始,然后遇到yield后,return出要生成的数,此步就结束。

#!/usr/bin/env python
# encoding: utf-8
'''
@Author  : 草木零
@Software: PyCharm
@File    : yield.py
@Time    : 2023/8/23 17:28
@desc   : yield详解
1.程序开始执行以后,因为yield_demo函数终有yield关键字,
所以test函数并不会真正的执行,而是先得到一个生成器y
2.直到调用next方法,yield_demo函数正式开始执行,先执行yield_demo函数中的print方法,然后进入while循环
3.程序遇到yield关键字,然后把yield想成是return,return了一个8之后,程序停止,
并没有执行赋值给a操作,此时next(y)语句执行完成,所以输出前面两行(第一行是while上面的print的结果,第二行是return出来的结果)
4.程序执行print("**********************")
5.又开始执行下面的print(next(y)),这个时候是从刚才next程序停止的地方开始执行,
也就是要执行a的赋值操作,这个时候因为赋值操作的右边是没有值的,已经被return出去了
这个时候a的值是none,所以接下来的输出是a:none
6.程序会继续在whili里执行,又一次碰到yield,这个时候同样return出8,然后程序停止。
print函数输出的8就是这次return出的8
'''def yield_demo():print('begin================')while True:a = yield 8print('a', a)y = yield_demo() # 这句不会打印出东西,因为test函数终有yield关键字,所以yield_demo函数并不会真正的执行,而是先得到一个生成器y
print(next(y))
print('*******************************')
print(next(y))
print('*******************************')

控制器:
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/87602.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/87602.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Nginx 动静分离原理与工作机制详解:从架构优化到性能提升

前言&#xff1a;在 Web 应用架构不断演进的今天&#xff0c;如何高效处理日益增长的访问量和复杂的业务逻辑&#xff0c;成为开发者必须面对的挑战。当我们在浏览器中打开一个网页&#xff0c;那些直观可见的 HTML 页面、精美绝伦的图片、流畅运行的 JavaScript 脚本&#xff…

介绍electron

一、Electron 是什么&#xff1f; Electron 是一个基于 Chromium 和 Node.js 的框架&#xff0c;允许开发者使用前端技术&#xff08;HTML/CSS/JavaScript&#xff09;构建原生桌面应用。其核心优势在于&#xff1a; 跨平台&#xff1a;一次开发&#xff0c;生成 Windows、ma…

DeepSeek与诡秘之主

1、大模型像个腐儒 其实从大模型的训练方式来看&#xff0c;它算不上天赋异禀。尤其在成长阶段&#xff0c;大模型那种种令人惊艳的表现&#xff0c;足够让人误以为这是个天才。 可人这种生物&#xff0c;注定是贪婪的。在大模型成长后期&#xff0c;伴随着各种技巧的验证&…

动手实践OpenHands系列学习笔记5:代理系统架构概述

笔记5&#xff1a;代理系统架构概述 一、引言 AI代理系统是一种能够自主执行任务的智能软件架构&#xff0c;OpenHands作为AI驱动的软件开发代理平台&#xff0c;拥有完整的代理系统架构设计。本笔记将探讨AI代理架构的基本原理&#xff0c;并通过分析OpenHands核心架构&…

智能电动汽车 --- 车辆网关路由缓存

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 简单,单纯,喜欢独处,独来独往,不易合同频过着接地气的生活,除了生存温饱问题之外,没有什么过多的欲望,表面看起来很高冷,内心热情,如果你身…

Spring中实现依赖注入(DI)的三种方式

1. Autowired 字段注入&#xff08;不推荐&#xff09;​ Service public class UserService {Autowired // 直接在字段上注入private UserRepository userRepository; } ​​原理​​&#xff1a;Spring 启动时扫描所有 Component、Service 等注解的类&#xff0c;发现 Aut…

Alpha系统联结大数据、GPT两大功能,助力律所管理降本增效

如何通过AI工具实现法律服务的提质增效,是每一位法律人都积极关注和学习的课题。但从AI技术火爆一下,法律人一直缺乏系统、实用的学习资料,来掌握在法律场景下AI的使用技巧。 今年5月,iCourt携手贵阳律协大数据与人工智能专业委员会,联合举办了《人工智能助力律师行业高质量发…

UI前端与数字孪生融合新趋势:智慧家居的智能化控制与个性化服务

hello宝子们...我们是艾斯视觉擅长ui设计、前端开发、数字孪生、大数据、三维建模、三维动画10年经验!希望我的分享能帮助到您!如需帮助可以评论关注私信我们一起探讨!致敬感谢感恩!一、引言&#xff1a;数字孪生重构智慧家居的技术范式在智能家居渗透率快速提升的今天&#xf…

R语言初学者爬虫简单模板

习惯使用python做爬虫的&#xff0c;反过来使用R语言可能有点不太习惯&#xff0c;正常来说R语言好不好学完全取决于你的学习背景以及任务复杂情况。对于入门学者来说&#xff0c;R语言使用rvesthttr组合&#xff0c;几行代码就能完成简单爬取&#xff08;比Python的Scrapy简单…

如何决定idea项目中使用的是哪个版本的jdk?是idea中配置决定的?还是maven中配置决定的

✅ IDEA 项目中使用哪个 JDK&#xff0c;是由以下几部分共同决定的&#xff1a; 阶段决定因素举例项目编译&#xff08;编译器&#xff09;IDEA 设置的 Project SDK 和模块 SDKProject Structure → Project / Modules 中配置的 JDKMaven 构建Maven 使用的 JDK&#xff08;即 …

Docker拉取bladex 、 sentinel-dashboard

docker pull bladex/sentinel-dashboard 是用于从 Docker Hub 拉取 Alibaba Cloud Sentinel Dashboard 镜像的命令&#xff0c;默认会拉取最新版本。以下是详细的操作步骤及注意事项&#xff1a; 操作步骤 1. 拉取镜像 &#xff1a;在终端输入 docker pull bladex/sentinel-…

从零开始理解 JavaScript 中的 `window.parent`、`top` 和 `self`

从零开始理解 JavaScript 中的 window.parent、top 和 self 在 JavaScript 开发中&#xff0c;window 对象是浏览器环境中最重要的全局对象之一。它不仅代表了浏览器窗口本身&#xff0c;还提供了对窗口层级关系的访问能力。对于处理嵌套框架&#xff08;iframe&#xff09;或…

vue3引入海康监控视频组件并实现非分屏需求一个页面同时预览多个监控视频;

海康监控视频非分屏需求&#xff0c;一个页面引用多个视频组件; js文件位置index.html 引入js文件//根据自己路径引入哈<script src"static/haiKangWeb3.0/jquery-1.7.1.min.js"></script><script type"text/javascript" id"videonode…

Policy Gradient【强化学习的数学原理】

目录 policy 与表格方式的区别&#xff1a; metric to define optimal policies 1. weighted averge 2. the average reward 问题&#xff1a; 梯度计算 如何理解policy-gradient&#xff1f; policy gradient与表格方式(value based)的区别&#xff1a; policy 通过参…

【深圳大学机器学习】实验一:PCA算法

实验目的 1、实现PCA算法的人脸重构&#xff0c;即用20,40,60,80,...,160个投影来重构图像的效果。 2、实现PCA算法的人脸识别&#xff0c;给出不少于三个人脸数据库上 10,20,30,...,160维的人脸识别识别率&#xff0c;并打印出识别率变化曲线图。 3、用PCA用来进行人脸图像…

编程中的英语

case this are mixed case version case在这里表示大小写&#xff1f;为什么case可以表示大小写的含义&#xff1f; “case”在这里的含义 在句子“This are mixed case version”中&#xff0c;“case”确实表示“大小写”&#xff0c;用于描述字母的形式&#xff08;大写字母…

LabVIEW开发关节轴承试验机

LabVIEW通过NI硬件&#xff08;CompactRIO 实时控制器、FPGA 模块等&#xff09;与模块化软件设计的结合&#xff0c;实现试验参数采集、多工况控制、数据存储的并行处理&#xff0c;体现LabVIEW 在工业自动化中对多任务并发场景的高效支持能力。 ​ 应用场景 关节轴承试验机…

【Linux庖丁解牛】— 动静态库的制作和使用!

1. 什么是库库是写好的现有的&#xff0c;成熟的&#xff0c;可以复⽤的代码。现实中每个程序都要依赖很多基础的底层库&#xff0c;不可能 每个⼈的代码都从零开始&#xff0c;因此库的存在意义⾮同寻常。 本质上来说库是⼀种可执⾏代码的⼆进制形式&#xff0c;可以被操作系统…

Hadoop集群启动 (ZooKeeper、HDFS、YARN、Hbase)

一、启动ZooKeeper集群 sh /opt/modules/zookeeper-3.4.14/bin/zkServer.sh start[hadoopcentos01 ~]$ sh /opt/modules/zookeeper-3.4.14/bin/zkServer.sh start ZooKeeper JMX enabled by default Using config: /opt/modules/zookeeper-3.4.14/bin/../conf/zoo.cfg Startin…

React Hooks全面解析:从基础到高级的实用指南

React Hooks全面解析&#xff1a;从基础到高级的实用指南 React Hooks自2018年16.8版本引入以来&#xff0c;彻底改变了React组件的开发方式。** Hooks使函数组件获得了与类组件同等的表达能力&#xff0c;同时简化了代码结构&#xff0c;提升了可维护性**。本文将系统介绍Rea…