How can I get an equivalent of Python threading.Timer that uses system uptime?
timer使用系统时间,但在我使用它时时间会发生变化,我如何才能让它使用系统正常运行时间?
我有一个python脚本,它可以做很多事情,其中之一就是设置系统时间。当这个脚本启动时,时间是错误的。此脚本还需要30秒的全局超时。
我一直在使用以下超时类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | class Timeout(object): def __init__(self, seconds=1, signum=signal.SIGUSR1, exception=TimeoutException): self.exception = exception self.pid = os.getpid() self.signum = signum self.timer = threading.Timer(seconds, self.exit_function) def exit_function(self): os.kill(self.pid, self.signum) def handle_timeout(self, signum, frame): raise self.exception() def __enter__(self): signal.signal(self.signum, self.handle_timeout) self.timer.start() def __exit__(self, type, value, traceback): self.timer.cancel() |
它包装了我的整个脚本:
1 2 | with Timeout(seconds=30): main() |
有时脚本会很快失败,或者在30秒后永远不会被杀死。我认为这是因为
我最终扩展了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | class Timer(threading._Timer): def __init__(self, *args, **kwargs): super(Timer, self).__init__(*args, **kwargs) # only works on Linux self._libc = ctypes.CDLL('libc.so.6') self._buf = ctypes.create_string_buffer(128) def uptime(self): self._libc.sysinfo(self._buf) return struct.unpack_from('@l', self._buf.raw)[0] def run(self): start_time = self.uptime() while not self.finished.is_set(): time.sleep(0.1) if self.uptime() - start_time > self.interval: self.function(*self.args, **self.kwargs) break self.finished.set() |
似乎您使用的是python<3.3。在python 3.3或更新版本上,
Return the value (in fractional seconds) of a monotonic clock, i.e. a clock that cannot go backwards. The clock is not affected by system clock updates.
因此,使用python>=3.3,
尝试解决您的问题:窗户
我看到一种选择,可以使用
1 2 3 4 | import ctypes kernel_32 = ctypes.cdll.LoadLibrary("Kernel32.dll") kernel_32.GetTickCount() # overflow after 49.7 days kernel_32.GetTickCount64() |
有了这个,你就可以用一些不好用的东西来创建你自己的计时器,比如:
1 2 3 4 5 6 | def sleep(time): start = kernel_32.GetTickCount64() end = start + time while kernel_32.GetTickCount64() < end: pass print('done') |
我真的希望这种方法有助于解决你的问题-祝你好运
编辑:Linux
基于单调:您可以尝试将其作为gettickCount1的替代方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | try: clock_gettime = ctypes.CDLL(ctypes.util.find_library('c'), use_errno=True).clock_gettime except Exception: clock_gettime = ctypes.CDLL(ctypes.util.find_library('rt'), use_errno=True).clock_gettime class timespec(ctypes.Structure): """Time specification, as described in clock_gettime(3).""" _fields_ = (('tv_sec', ctypes.c_long), ('tv_nsec', ctypes.c_long)) if sys.platform.startswith('linux'): CLOCK_MONOTONIC = 1 elif sys.platform.startswith('freebsd'): CLOCK_MONOTONIC = 4 elif sys.platform.startswith('sunos5'): CLOCK_MONOTONIC = 4 elif 'bsd' in sys.platform: CLOCK_MONOTONIC = 3 elif sys.platform.startswith('aix'): CLOCK_MONOTONIC = ctypes.c_longlong(10) def monotonic(): """Monotonic clock, cannot go backward.""" ts = timespec() if clock_gettime(CLOCK_MONOTONIC, ctypes.pointer(ts)): errno = ctypes.get_errno() raise OSError(errno, os.strerror(errno)) return ts.tv_sec + ts.tv_nsec / 1.0e9 |
1:版权所有2014、2015、2016 Ori Livneh根据Apache许可证2.0版(以下简称"许可证")获得许可;除非符合许可证,否则您不能使用此文件。您可以在以下网址获得许可证副本:http://www.apache.org/licenses/license-2.0除非适用法律要求或书面同意,软件根据许可证分发是按"原样"分发的,无任何明示或暗示的保证或条件。