相关文章推荐
曾经爱过的南瓜  ·  Unable to open socket ...·  1 月前    · 
干练的馒头  ·  Java处理Exception无法捕获的异常 ...·  1 月前    · 
温文尔雅的鸵鸟  ·  C++ 内存分配可视化_内存可视化·  4 周前    · 
帅呆的佛珠  ·  Jmeter之读取csv文件踩坑记 - 梁剑lj ·  4 周前    · 
逼格高的橙子  ·  QtXml:QDomDocument、QDo ...·  1 年前    · 
才高八斗的钢笔  ·  一文探讨如何从扩散模型中反向提取出训练数据 ...·  2 年前    · 
俊逸的火锅  ·  OpenSAML - 极客挖掘机 - 博客园·  2 年前    · 
活泼的抽屉  ·  python-docx获取word的自动编号 ...·  2 年前    · 
英姿勃勃的鸡蛋面  ·  如何使用numpy.void类型_pytho ...·  2 年前    · 
Code  ›  一日一技:除了 time.sleep,你还有一个暂停代码的方法开发者社区
event 线程
https://cloud.tencent.com/developer/article/1739310
苦恼的小蝌蚪
2 年前
作者头像
青南
0 篇文章

一日一技:除了 time.sleep,你还有一个暂停代码的方法

前往专栏
腾讯云
开发者社区
文档 意见反馈 控制台
首页
学习
活动
专区
工具
TVP
文章/答案/技术大牛
发布
首页
学习
活动
专区
工具
TVP
返回腾讯云官网
社区首页 > 专栏 > 未闻Code > 一日一技:除了 time.sleep,你还有一个暂停代码的方法

一日一技:除了 time.sleep,你还有一个暂停代码的方法

作者头像
青南
发布 于 2020-11-03 14:55:42
978 0
发布 于 2020-11-03 14:55:42
举报

我们知道,在 Python 里面可以使用 time.sleep 来让代码暂停一段时间,例如:

import time
print('...部分代码...')
time.sleep(5)
print('...剩下的代码...')

程序首先打印出 ...部分代码... ,然后等待5秒钟,再打印出 ...剩下的代码... 。

现在大家想一想,有没有什么办法,在不使用 time.sleep 的情况下,让程序暂停5秒?

你可能会说,用 requests 访问一个延迟5秒的网址、或者用递归版算法计算斐波那契数列第36位……这些奇技淫巧。

不过今天我说的,是另外一个东西, threading 模块里面的 Event 。

我们来看看它的用法:

import threading
event = threading.Event()
print('...部分代码...')
event.wait(5)
print('...剩下的代码...')

这样一来,程序首先打印出 ...部分代码... ,然后等待5秒钟,再打印出 ...剩下的代码... 。

功能看起来跟 time.sleep 没什么区别,那为什么我要特别提到它呢?因为在多线程里面,它比 time.sleep 更有用。我们来看一个例子:

import threading
class Checker(threading.Thread):
    def __init__(self, event):
        super().__init__()
        self.event = event
    def run(self):
        while not self.event.is_set():
            print('检查 redis 是否有数据')
            time.sleep(60)
trigger_async_task()
event = threading.Event()
checker = Checker(event)
checker.start()
if user_cancel_task():
    event.set()

我来解释一下这段代码的意思。在主线程里面,我调用 trigger_async_task() 触发了一个异步任务。这个任务多久完成我并不清楚。但是这个任务完成以后,它会往 Redis 里面发送一条消息,只要 Redis 有这个消息了,我就知道它完成了。所以我要创建一个 checker 子线程,每60秒去 Redis里面检查任务是否完成。如果没有完成,就暂停60秒,然后再检查。

但某些情况下,我不需要等待了,例如用户主动取消了任务。这个时候,我就想提前结束这个 checker 子线程。

但是我们知道,线程是不能从外面主动杀死的,只能让它自己退出。所以当我执行 event.set() 后,子线程里面 self.event.is_set() 就会返回 False,于是这个循环就不会继续执行了。

可是,如果某一轮循环刚刚开始,我在主线程里面调用了 event.set() 。此时,子线程还在 time.sleep 中,那么子线程需要等待60秒才会退出。

但如果我修改一下代码,使用 self.event.wait(60) :

import threading
class Checker(threading.Thread):
    def __init__(self, event):
        super().__init__()
        self.event = event
    def run(self):
        while not self.event.is_set():
            print('检查 redis 是否有数据')
            self.event.wait(60)
trigger_task()
 
推荐文章
曾经爱过的南瓜  ·  Unable to open socket file: target process not responding or HotSpot VM not loaded The -F option can
1 月前
干练的馒头  ·  Java处理Exception无法捕获的异常 - 迷失之路
1 月前
温文尔雅的鸵鸟  ·  C++ 内存分配可视化_内存可视化
4 周前
帅呆的佛珠  ·  Jmeter之读取csv文件踩坑记 - 梁剑lj
4 周前
逼格高的橙子  ·  QtXml:QDomDocument、QDomNode - 知乎
1 年前
才高八斗的钢笔  ·  一文探讨如何从扩散模型中反向提取出训练数据 - 知乎
2 年前
俊逸的火锅  ·  OpenSAML - 极客挖掘机 - 博客园
2 年前
活泼的抽屉  ·  python-docx获取word的自动编号_python获取word标题号_莫魇的博客-CSDN博客
2 年前
英姿勃勃的鸡蛋面  ·  如何使用numpy.void类型_python_Mangs-Python
2 年前
今天看啥   ·   Py中国   ·   codingpro   ·   小百科   ·   link之家   ·   卧龙AI搜索
删除内容请联系邮箱 2879853325@qq.com
Code - 代码工具平台
© 2024 ~ 沪ICP备11025650号