如何使用Twisted Clock类顺序执行多阶段延迟任务并规避time.sleep
Fixing Sequential Delays with Twisted's Clock Class
It looks like your code has a few key issues that are preventing the delays from working as expected—let's break down the problems and fix them step by step.
Key Issues in Your Original Code
- Multiple Clock Instances: You're creating a new
Clockin each method, so advancing one clock doesn't affect the others. All tasks need to share the same clock to coordinate timing. - Immediate Function Execution: When you pass
self.end_time()toadditionalFunc, you're callingend_timeimmediately instead of waiting for the delay. - Unchained Tasks: Your Deferreds aren't linked together, so both tasks run at the same time instead of sequentially.
- Class-level Start Time:
start_timeis a class variable, so it's set when the class is defined (not when you create an instance), which isn't what you want for per-instance timing.
Corrected Code
from twisted.internet.task import Clock from twisted.internet.defer import Deferred, inlineCallbacks class ControlTime: def __init__(self): # Initialize start time when the instance is created self.clock = Clock() self.start_time = self.clock.seconds() def end_time(self): # Use the Clock's time for consistent simulation current_end_time = self.clock.seconds() print(f"End time recorded: {current_end_time}") return current_end_time def additionalFunc(self, end_time_val): total_delay = end_time_val - self.start_time print(f'You have delayed for: {total_delay} s') @inlineCallbacks def run_sequential_tasks(self, first_delay=0, second_delay=0): # Wait for the first delay before running end_time yield self._wait_for_delay(first_delay) end_val = self.end_time() # Wait for the second delay before running the print function yield self._wait_for_delay(second_delay) self.additionalFunc(end_val) def _wait_for_delay(self, delay): # Helper to wrap callLater in a Deferred for easy chaining deferred = Deferred() self.clock.callLater(delay, deferred.callback, None) return deferred # Usage example if __name__ == "__main__": ctrl = ControlTime() # Run tasks: first delay 3s, then another 3s ctrl.run_sequential_tasks(first_delay=3, second_delay=3) # Advance the clock to trigger the first delay ctrl.clock.advance(3) # Advance again to trigger the second delay ctrl.clock.advance(3)
What Changed & Why
- Single Clock Instance: We initialize one
Clockin the class constructor, so all scheduled tasks use the same clock. Advancing this clock will trigger all pending tasks in order. - Chained Tasks with
inlineCallbacks: This decorator lets us write sequential asynchronous code like synchronous code. We first wait for the initial delay, runend_timeto get the end value, wait for the second delay, then pass that value toadditionalFunc. - Helper
_wait_for_delayMethod: This wrapscallLaterin a Deferred, making it easy to wait for delays usingyield. - Instance-level Start Time:
start_timeis now set in__init__, so each instance gets its own start time when it's created. - No Immediate Function Calls: We call
end_timeonly after the first delay, then pass its return value toadditionalFuncafter the second delay—no more immediate execution.
Testing with Real Time (Optional)
If you want to use real delays instead of a simulated Clock, replace self.clock with twisted.internet.reactor and remove the clock.advance calls. Your code will then use actual wall-clock time:
from twisted.internet import reactor # Inside __init__: self.clock = reactor # Usage: ctrl.run_sequential_tasks(3, 3) reactor.run()
内容的提问来源于stack exchange,提问作者Working dollar
相关产品推荐
相关产品推荐

