简体   繁体   中英

Invalid Argument when implementing sched

I've written a basic wrapper around sched.scheduler , but I'm getting:

  File "/usr/local/anaconda3/lib/python3.7/sched.py", line 149, in run
    delayfunc(time - now)
OSError: [Errno 22] Invalid argument

What is the cause of this error? I'm following https://docs.python.org/3/library/sched.html

Code:

#!/usr/local/anaconda3/bin/python

from time import time, sleep
from datetime import datetime, timezone
from sched import scheduler

class Scheduler:
    # specify one or t'other  e.g. "2021-03-17 02:29:00"
    def __init__(self, event_time_utc:str='', local_unix_timestamp_override:float=0):
        self.event_local_timestamp = Scheduler.to_local_unix_timestamp(event_time_utc) \
            if event_time_utc else local_unix_timestamp_override

        # self.seconds_until_event = event_local_timestamp - time()

        print(self.event_local_timestamp - time())

        self.sch = scheduler()

    def run(self, blocking=False):
        self.sch.run(blocking)


    @staticmethod
    def to_local_unix_timestamp(time_utc: str):
        dt_utc = datetime.strptime(time_utc, "%Y-%m-%d %H:%M:%S")
        dt_local = dt_utc.replace(tzinfo=timezone.utc)
        return dt_local.timestamp()


    @staticmethod
    def to_human_readable(unix_timestamp):
        return datetime.fromtimestamp(unix_timestamp).strftime('%Y-%m-%d %H:%M:%S.%f')


    def schedule(self, offset_from_event_time_s:float, callback):
        print('Event scheduled for local unix timestamp:', self.event_local_timestamp + offset_from_event_time_s)

        self.sch.enterabs(
            time = self.event_local_timestamp + offset_from_event_time_s,
            priority = 1,
            action = callback
            )


if __name__ == '__main__':
    sch = Scheduler(local_unix_timestamp_override=time()+5)

    print(f'Started at time: {Scheduler.to_human_readable(time())}')

    def callback():
        print(f'Callback at time: {Scheduler.to_human_readable(time())}')

    sch.schedule(offset_from_event_time_s=1, callback=callback)

    sch.run(blocking=True)

Output:

> ./scheduler.py 
4.999997854232788
Started at time: 2021-03-17 11:00:03.424191
f 1615953609.424139
Traceback (most recent call last):
  File "./scheduler.py", line 55, in <module>
    sch.run(blocking=True)
  File "./scheduler.py", line 20, in run
    self.sch.run(blocking)
  File "/usr/local/anaconda3/lib/python3.7/sched.py", line 149, in run
    delayfunc(time - now)
OSError: [Errno 22] Invalid argument

The root of the problem is that YOU are assuming that the sched module is using time.time() for its timing function. That is a false assumption. It is using time.monotonic() by default, which returns the time since your program started. That is going to be a small number, like 6. When you try to delay until 1615644884.1231558, that makes it go crazy.

Change this:

        self.sch = scheduler()

to this:

        self.sch = scheduler(time)

I tried debugging the issue and found that the max length of floating point value allowed in time.sleep() is 8 (I couldn't find any resource on why only 8) but since you are using timestamp the value exceeds that. You can try following code on your machine and check that:

import time

# Will work fine
time.sleep(16156448)
    
# Will result in error
time.sleep(1615644884.1231558)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM