Search code examples
pythontimerpython-multithreadingbuilt-in

Python how to pass infinite timeout to threading.Timer's interval argument


I am using a threading.Timer and am trying to pass in math.inf (+infinity) to its interval argument. Please see the below sample code and traceback for exactly what I mean.

My questions are:

  • How can I pass in infinity to the interval input to Timer?
  • Aside: is this a bug in Python?
    • Do you think Timer should be able to handle math.inf as a value for the interval argument?

Sample Code

from math import inf
from threading import Timer


def call_func_later(func, timeout_sec: float = None) -> None:
    """Call the input func after some time (sec)."""
    Timer(interval=timeout_sec or inf, function=func).start()


placeholder_func = lambda *args: None

call_func_later(placeholder_func)

Running this with Python 3.8.5 immediately throws the following traceback:

Exception in thread Thread-1:
Traceback (most recent call last):
  File "/path/to/.pyenv/versions/3.8.5/lib/python3.8/threading.py", line 932, in _bootstrap_inner
    self.run()
  File "/path/to/.pyenv/versions/3.8.5/lib/python3.8/threading.py", line 1252, in run
    self.finished.wait(self.interval)
  File "/path/to/.pyenv/versions/3.8.5/lib/python3.8/threading.py", line 558, in wait
    signaled = self._cond.wait(timeout)
  File "/path/to/.pyenv/versions/3.8.5/lib/python3.8/threading.py", line 306, in wait
    gotit = waiter.acquire(True, timeout)
OverflowError: timestamp too large to convert to C _PyTime_t

Solution

  • My best approximation for a max is acquired from this answer: https://stackoverflow.com/a/45704244/11163122

    # 64-bit integer, converted from nanoseconds to seconds, and subtracting 0.1
    # just to be in bounds.  SEE: https://stackoverflow.com/a/45704244/11163122
    MAX_TIMEOUT_SEC = 2 ** 63 / 1e9 - 0.1
    

    This value is 9,223,372,036.754776 seconds, which converts to ~292 years.

    As I'll probably be dead and gone by then, I will use that value instead of math.inf.