Skip to content

Allow sleeping until an absolute time #101558

Description

@haukex

I propose a version of time.sleep() that allows for the specification of absolute times.

Python 3.11 added the use of clock_nanosleep in time.sleep() (#28111), and both it and Windows' SetWaitableTimerEx allow for the specification of absolute times. This can be useful for writing simple loops that trigger at an interval that is tied to wall-clock time, which has many applications: triggering taking of measurements, pictures, checking status, sending messages, ...

With time.sleep(), one has to emulate this by saying time.sleep(deadline - time.time()), which pysleep then calculates back into an absolute time internally, which adds inaccuracy.

I will be submitting a pull request shortly that modifies pysleep to give it an "absolute" argument and adds a time.sleep_until() function.

Linked PRs

Activity

  1. added a commit that references this issue on Feb 4, 2023
  2. added
    stdlibStandard Library Python modules in the Lib/ directory
    on Feb 4, 2023
  3. SimpleArt commented on Feb 5, 2023

    @SimpleArt

    Worth pointing out that I would love to have the equivalent functions like asyncio.sleep_until. Not sure if there's any other sleepers to look for.

  4. haukex commented on Feb 6, 2023

    @haukex
    ContributorAuthor

    I checked the implementation, and loop.time() is just time.monotonic(), and the loop is apparently implemented with select() (from selectors or IocpProactor on Windows). I'm not an expert on this but it seems like it might be fairly complicated to implement on a low level, so perhaps in that case it would need to be implemented at a higher level.

  5. self-assigned this
    on Feb 6, 2023
  6. added a commit that references this issue on Feb 11, 2023
  7. haukex commented on Feb 12, 2023

    @haukex
    ContributorAuthor

    Additional arguments for this feature suggestion provided here: #101559 (comment)

  8. added a commit that references this issue on Feb 12, 2023
  9. SimpleArt commented on Mar 15, 2023

    @SimpleArt

    I think that for asyncio it's possible to use what asyncio.sleep already uses underneath. On the first call, an estimate of loop.time() could be made in absolute time, and every subsequent call is relative to that time by sleeping until loop.time() + (timestamp - abs_loop_time), calling what asyncio.sleep uses. This prevents accumulated inaccuracies if multiple asyncio.sleep(seconds) calls are made instead of using multiple asyncio.sleep_until(timestamp).

  10. haukex commented on Mar 18, 2023

    @haukex
    ContributorAuthor

    I still don't know of an async equivalent of the system call clock_nanosleep - and this system function is the main reason I raised this issue. But perhaps loop.call_at can be used in the emulation for asyncio.

  11. jcalvinowens commented on Jan 22, 2024

    @jcalvinowens

    I'd love to see the PR attached here merged. To implement a periodic task in a Python loop, one is currently forced to do a racy subtraction with the current time. The pull request attached to this proposal fixes that.

    To print 'A' at 100hz, one might naively write:

        while True:
                print('A')
                time.sleep(0.01)
    

    ...but of course, that's not really going to yield a coherent 100hz. There are many applications where that matters, such as sampling a sensor to produce timeseries data.

    If you actually care, you're forced to do something like this:

        p = time.time()
        while True:
                print('A')
                time.sleep(time.time() - p + 0.01)
                p = time.time()
    

    ...but that's inherently racy. If this proposal is implemented, that loop could become:

        p = time.time()
        while True:
                print('A')
                time.sleep_until(p + 0.01)
                p += 0.01
    

    ...which both simplifies the code, and eliminates the race condition. On platforms where there isn't support for TIMER_ABSTIME, it could fall back to the racy subtraction (which is what the user would've done anyway).

  12. hauntsaninja commented on Sep 17, 2024

    @hauntsaninja
    Contributor

    pganssle's comment sums up the current state here: #101559 (comment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

stdlibStandard Library Python modules in the Lib/ directorytype-featureA feature request or enhancement

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions