python - 如何在类中使用充当倒数计时器的线程?
问题描述
我想定义一个包含id
,status
和的对象countdown timer
。一旦我实例化了这个对象,倒数计时器应该立即启动。
下面是我创建一个类的代码,该类中定义了倒数计时器的非线程版本
import time
import sys
from threading import Timer
class UserTimer:
def __init__(self, id=None, current_status=None):
self.id = id
self.current_status = current_status
self.timeout()
def timeout(self):
print("timeout started for", self.id)
timeout_limit = 150
seconds = 0
while True:
try:
if seconds == timeout_limit:
print("countdown over for", self.id)
break
time.sleep(1)
seconds += 1
except KeyboardInterrupt, e:
break
下面是如何实例化它
params1 = {'id': "test@hello.com", 'current_status': "success"}
params2 = {'id': "test2@hello.com", 'current_status': "success"}
user1 = UserTimer(**params1)
user2 = UserTimer(**params2)
这里的问题是,当这个程序运行时,它将实例化第一个对象 ( user1
),并且由于函数的原因,它会在实例化第二个对象 ( )time.sleep()
之前等待给定的持续时间user2
因此,我随后查找并发现 python 线程在这种情况下很有帮助,因为线程将独立运行并且不会阻塞代码的进程。
所以这就是我更改下面代码的方式
class UserTimer:
def __init__(self, id=None, current_status=None):
self.id = id
self.current_status = current_status
def timeout(self):
print("time over for", self.id)
t = Timer(150, timeout)
t.start()
params1 = {'id': "test@hello.com", 'current_status': "success"}
params2 = {'id': "test2@hello.com", 'current_status': "success"}
user1 = UserTimer(**params1)
user2 = UserTimer(**params2)
现在两个对象同时实例化,但问题是一旦给定持续时间结束,就会出现以下错误
Exception in thread Thread-1:
Traceback (most recent call last):
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/threading.py", line 801, in __bootstrap_inner
self.run()
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/threading.py", line 1073, in run
self.function(*self.args, **self.kwargs)
TypeError: timeout() takes exactly 1 argument (0 given)
这是因为它看到了self
它不期望的关键字。但我需要,self
因为我需要转储有关用户对象的一些信息。如果我删除self
,那么它运行良好。
我是否以错误的方式在类中定义线程?我想要的是能够实例化具有自己的倒数计时器的多个对象。
此外,我还应该能够通过执行类似的操作来重置倒数计时器user1.reset_timer = True
我在这里做错了什么?
解决方案
我从你的代码中得到了一个与你不同的错误:
TypeError: timeout() missing 1 required positional argument: 'self'
线索是提到self
这是由以下原因引起的:
t = Timer(150, timeout)
t.start()
您在 的类主体中UserTimer
,这意味着它在定义类时执行(并且self
尚未创建实例)。
解决这个问题的一个简单方法是通过定义一个__call__()
方法(并在正确的时间调用它)使类的实例可调用。这就是我的意思:
import time
import sys
from threading import Timer
class UserTimer:
def __init__(self, id=None, current_status=None, interval=5):
self.id = id
self.current_status = current_status
self.interval = interval
def timeout(self):
print("time over for", self.id)
def __call__(self):
self.timer_thread = Timer(self.interval, self.timeout)
self.timer_thread.start()
def cancel(self):
try:
self.timer_thread.cancel()
except AttributeError:
raise RuntimeError("'UserTimer' object not started.")
params1 = dict(id="test@hello.com", current_status="success")
params2 = dict(id="test2@hello.com", current_status="success", interval=6)
user1 = UserTimer(**params1)
user1() # Start Timer.
user2 = UserTimer(**params2)
user2() # Start Timer.
我还cancel()
根据您的要求添加了该方法,并使时间间隔成为一个易于更改的变量,而不是将其硬编码到类的主体中。
推荐阅读
- angular - 在自定义指令中使用 ViewChild/ContentChild 在 mat-form-field 中查找 input[matInput]
- python - 在类方法中声明一个全局变量
- mysql - MySQL:WHERE table.column(current_date),如果今天日期的列值等于特定值,则评估表达式
- macos - SwiftUI CoreData 异步获取
- powershell - 在 Powershell 中替换部分 Select 语句
- powershell - Powershell GetChildItem 使用错误的路径来查找匹配项
- javascript - 有没有办法在初始化时过滤数据表?
- javascript - Apollo Client v3 中的手动数据规范化
- oracle - Oracle 中的 SQL 监控
- linux - 在目录中的文件中查找列表的一个单词