如何在 class 中使用线程作为倒数计时器?
How to use threads inside a class that act as a countdown timer?
我想定义一个包含 id
、status
和 countdown timer
的对象。一旦我实例化这个对象,倒数计时器应该立即开始。
下面是我创建 class 的代码,其中定义了一个非线程版本的倒数计时器
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)
这里的问题是当这个程序运行s时,它会实例化第一个对象(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
,那么 运行 没问题。
我是否以错误的方式在 class 中定义线程?我想要的是能够实例化多个具有自己的倒数计时器的对象。
此外,我还应该能够通过 user1.reset_timer = True
之类的操作来重置倒数计时器
我做错了什么?
你应该把Timer的初始化放在__init__()
里面,在你实例化一个对象的时候启动它。
class UserTimer(object):
def __init__(self, id=None, current_status=None):
self.id = id
self.current_status = current_status
self.start_timer() # start timer when an object is instantiated
def timeout(self):
print("time over for", self.id)
def start_timer(self):
self.t = Timer(5, self.timeout) # changed to 5 seconds for demo
# `self.timeout` instead of `timeout`
self.t.start()
def reset_timer(self):
self.t.cancel() # cancel old timer
self.start_timer() # and start a new one
params1 = {'id': "test@hello.com", 'current_status': "success"}
params2 = {'id': "test2@hello.com", 'current_status': "success"}
user1 = UserTimer(**params1)
time.sleep(2) # assuming that user2 is instantiated 2 seconds later
print('instantiating user2...')
user2 = UserTimer(**params2)
time.sleep(3) # reset user1's timer 3 seconds after user2 instantiation
print('reseting timer of user1...')
user1.reset_timer()
您可以运行代码并查看时间。
我从你的代码中得到的错误与你的不同:
TypeError: timeout() missing 1 required positional argument: 'self'
线索是提到 self
是由以下原因引起的:
t = Timer(150, timeout)
t.start()
你在 UserTimer
的 class 主体中,这意味着它在定义 class 时执行(并且尚未创建 self
实例) .
解决这个问题的一个简单方法是通过定义 __call__()
方法(并在正确的时间调用它)来使 class 的实例可调用。这就是我的意思:
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()
方法,并使时间间隔成为一个易于更改的变量,而不是将其也硬编码到 class 的主体中。
我想定义一个包含 id
、status
和 countdown timer
的对象。一旦我实例化这个对象,倒数计时器应该立即开始。
下面是我创建 class 的代码,其中定义了一个非线程版本的倒数计时器
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)
这里的问题是当这个程序运行s时,它会实例化第一个对象(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
,那么 运行 没问题。
我是否以错误的方式在 class 中定义线程?我想要的是能够实例化多个具有自己的倒数计时器的对象。
此外,我还应该能够通过 user1.reset_timer = True
我做错了什么?
你应该把Timer的初始化放在__init__()
里面,在你实例化一个对象的时候启动它。
class UserTimer(object):
def __init__(self, id=None, current_status=None):
self.id = id
self.current_status = current_status
self.start_timer() # start timer when an object is instantiated
def timeout(self):
print("time over for", self.id)
def start_timer(self):
self.t = Timer(5, self.timeout) # changed to 5 seconds for demo
# `self.timeout` instead of `timeout`
self.t.start()
def reset_timer(self):
self.t.cancel() # cancel old timer
self.start_timer() # and start a new one
params1 = {'id': "test@hello.com", 'current_status': "success"}
params2 = {'id': "test2@hello.com", 'current_status': "success"}
user1 = UserTimer(**params1)
time.sleep(2) # assuming that user2 is instantiated 2 seconds later
print('instantiating user2...')
user2 = UserTimer(**params2)
time.sleep(3) # reset user1's timer 3 seconds after user2 instantiation
print('reseting timer of user1...')
user1.reset_timer()
您可以运行代码并查看时间。
我从你的代码中得到的错误与你的不同:
TypeError: timeout() missing 1 required positional argument: 'self'
线索是提到 self
是由以下原因引起的:
t = Timer(150, timeout)
t.start()
你在 UserTimer
的 class 主体中,这意味着它在定义 class 时执行(并且尚未创建 self
实例) .
解决这个问题的一个简单方法是通过定义 __call__()
方法(并在正确的时间调用它)来使 class 的实例可调用。这就是我的意思:
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()
方法,并使时间间隔成为一个易于更改的变量,而不是将其也硬编码到 class 的主体中。