Reputation: 1562
When sleeping for a long time (like running time.sleep(3**3**3)
) in Python 3, the program returns an OverflowError with the error message "timestamp too large to convert to C _PyTime_t". What is the largest time length I can sleep?
Upvotes: 6
Views: 4794
Reputation: 63262
In Python 3.11.0 under Ubuntu 20.04, the previous answers raise exceptions with time.sleep
:
threading.TIMEOUT_MAX
raises OSError: [Errno 22] Invalid argument
2 ** 63 / 10 ** 9
or (2**63 - 1)//(10**9)
raises OSError: [Errno 22] Invalid argument
The following however works:
> import datetime, time
> max_years = 292 # Ref: https://github.com/python/cpython/blob/889b0b9bf95651fc05ad532cc4a66c0f8ff29fc2/Include/cpython/pytime.h
> sleep_time = datetime.timedelta(days=max_years * 365).total_seconds()
> sleep_time
9208512000.0
> time.sleep(sleep_time) # This works.
The reason for using the defined number of years is the following comment in pytime.h
:
// The _PyTime_t API supports a resolution of 1 nanosecond. The _PyTime_t type
// is signed to support negative timestamps. The supported range is around
// [-292.3 years; +292.3 years]. Using the Unix epoch (January 1st, 1970), the
// supported date range is around [1677-09-21; 2262-04-11].
Using 292.3 failed to work from inside a Docker container based on python:3.11-slim-buster
, raising OSError
, but 292 worked.
Bonus: Here is a function to sleep for long periods, as long as +inf:
def sleep_long(secs: int | float) -> None:
"""Sleep for up to an extended number of seconds, beyond what `time.sleep` may natively support."""
# Ref: https://stackoverflow.com/a/74712113/
max_secs = 9208512000 # Ref: datetime.timedelta(days=292 * 365).total_seconds()
if secs <= max_secs:
time.sleep(secs)
else:
while secs > 0:
sleep_time = min(secs, max_secs)
time.sleep(sleep_time)
secs -= max_secs
Upvotes: 1
Reputation: 1379
I found the following from the documentation of the threading library:
threading.TIMEOUT_MAX
The maximum value allowed for the timeout parameter of blocking functions (Lock.acquire(), RLock.acquire(), Condition.wait(), etc.). Specifying a timeout greater than this value will raise an OverflowError.
New in version 3.2.
On my system, with python 3.8:
>>> import threading
>>> threading.TIMEOUT_MAX
9223372036.0
I don't see it clearly specified anywhere that threading.TIMEOUT_MAX
is a maximum for the argument to time.sleep()
, but it appears to be the right value (or "close", for some reason), constructed with the same constraints.
Upvotes: 0
Reputation: 1562
The value should be 9223372036.854775, which is "is the maximum value for a 64-bit signed integer in computing". See this Wikipedia article.
Mentioning of
_PyTime_t
in PEP 564:The CPython private "pytime" C API handling time now uses a new _PyTime_t type: simple 64-bit signed integer (C int64_t). The _PyTime_t unit is an implementation detail and not part of the API. The unit is currently 1 nanosecond.
>>> 2 ** 63 / 10 ** 9
9223372036.854776
>>> time.sleep(9223372036.854775)
^CTraceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyboardInterrupt
>>> time.sleep(9223372036.854776)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
OverflowError: timestamp too large to convert to C _PyTime_t
>>>
Upvotes: 5