退出范围后 threading.Timer 的生命周期
Lifetime of threading.Timer after exiting scope
假设我有一个启动 Timer
的函数来调用其他方法 foo
:
def set_a_timer():
my_timer = threading.Timer(1200, foo)
my_timer.start()
...
return None
现在,此函数将 return 在计时器完成之前很久,并且在 1200 秒结束之前可能不会在我的程序中再次调用。程序 将 一直保持 运行。
我知道垃圾收集往往会负责删除超出范围的变量。这意味着我将无法在程序中再次访问 my_timer
。很好 - 我只需要它在 1200 秒内执行。但是在这 1200 秒之后它仍然会执行 foo
,还是会在它有机会之前被垃圾收集器清理掉?
简短的回答是:计时器仍将 运行。
长话短说,您在这里混淆了变量和值。变量超出范围,但这对值没有任何影响。 (对于 del
也是如此;它只是删除变量,而不是值。)
只有当对值的最后一次引用消失时,该值才会变成垃圾。 (在 CPython 中,如果该值不涉及引用循环,这意味着它会立即被销毁;在大多数其他实现中,它会稍后被销毁 — 一旦 GC 注意到它。)
Timer
class 是 Thread
的子class。线程通过在后台线程中调用 run
方法来工作。该方法的栈帧引用了它需要的任何东西,比如函数对象本身,以及所有局部变量,就像每个函数一样,所以这些值在该方法完成之前不会变成垃圾。其中一个局部变量是 self
,因此 Timer
对象本身仍然被引用,因此不是垃圾。
(如果你查看 Timer
的源代码——从文档链接——你可以看到它的 run
方法所做的基本上只是睡眠等待 Event
1200 秒,然后调用 foo
函数。)
如果您想查看 Timer
对象何时被销毁,您可以子class 它并添加一个 __del__
方法来打印一条消息(或者甚至让它打印那时整个堆栈)。
假设我有一个启动 Timer
的函数来调用其他方法 foo
:
def set_a_timer():
my_timer = threading.Timer(1200, foo)
my_timer.start()
...
return None
现在,此函数将 return 在计时器完成之前很久,并且在 1200 秒结束之前可能不会在我的程序中再次调用。程序 将 一直保持 运行。
我知道垃圾收集往往会负责删除超出范围的变量。这意味着我将无法在程序中再次访问 my_timer
。很好 - 我只需要它在 1200 秒内执行。但是在这 1200 秒之后它仍然会执行 foo
,还是会在它有机会之前被垃圾收集器清理掉?
简短的回答是:计时器仍将 运行。
长话短说,您在这里混淆了变量和值。变量超出范围,但这对值没有任何影响。 (对于 del
也是如此;它只是删除变量,而不是值。)
只有当对值的最后一次引用消失时,该值才会变成垃圾。 (在 CPython 中,如果该值不涉及引用循环,这意味着它会立即被销毁;在大多数其他实现中,它会稍后被销毁 — 一旦 GC 注意到它。)
Timer
class 是 Thread
的子class。线程通过在后台线程中调用 run
方法来工作。该方法的栈帧引用了它需要的任何东西,比如函数对象本身,以及所有局部变量,就像每个函数一样,所以这些值在该方法完成之前不会变成垃圾。其中一个局部变量是 self
,因此 Timer
对象本身仍然被引用,因此不是垃圾。
(如果你查看 Timer
的源代码——从文档链接——你可以看到它的 run
方法所做的基本上只是睡眠等待 Event
1200 秒,然后调用 foo
函数。)
如果您想查看 Timer
对象何时被销毁,您可以子class 它并添加一个 __del__
方法来打印一条消息(或者甚至让它打印那时整个堆栈)。