Examples#

Timestamp Resolution Example#

1import time
2
3import win_precise_time as wpt
4
5for _ in range(20):
6    print(f"{time.time()=:.9f} - {wpt.time()=:.9f}")

Output:

time.time()=1665189245.756171703 - wpt.time()=1665189245.756698370
time.time()=1665189245.756171703 - wpt.time()=1665189245.756715059
time.time()=1665189245.756171703 - wpt.time()=1665189245.756718636
time.time()=1665189245.756171703 - wpt.time()=1665189245.756721973
time.time()=1665189245.756171703 - wpt.time()=1665189245.756725311
time.time()=1665189245.756171703 - wpt.time()=1665189245.756728649
time.time()=1665189245.756171703 - wpt.time()=1665189245.756731749
time.time()=1665189245.756171703 - wpt.time()=1665189245.756735563
time.time()=1665189245.756171703 - wpt.time()=1665189245.756738901
time.time()=1665189245.756171703 - wpt.time()=1665189245.756742001
time.time()=1665189245.756171703 - wpt.time()=1665189245.756745338
time.time()=1665189245.756171703 - wpt.time()=1665189245.756748676
time.time()=1665189245.756171703 - wpt.time()=1665189245.756752014
time.time()=1665189245.756171703 - wpt.time()=1665189245.756755829
time.time()=1665189245.756171703 - wpt.time()=1665189245.756758928
time.time()=1665189245.756171703 - wpt.time()=1665189245.756762028
time.time()=1665189245.756171703 - wpt.time()=1665189245.756765366
time.time()=1665189245.756171703 - wpt.time()=1665189245.756768465
time.time()=1665189245.756171703 - wpt.time()=1665189245.756771326
time.time()=1665189245.756171703 - wpt.time()=1665189245.756774426

win_precise_time.time() always provides a fresh timestamp while the builtin time.time() is updated every 15ms.

Soft Realtime Example#

 1"""Python soft realtime example"""
 2
 3import os
 4from ctypes import windll
 5from enum import IntEnum
 6
 7import win_precise_time as wpt
 8
 9
10class SoftRealtime1ms:
11    def __init__(self) -> None:
12        self._stopped = False
13
14        self._cycle_time_ns = 1_000_000  # 1 millisecond
15        self._counter = self._cycle_time_ns
16
17        self._t0 = wpt.time()
18        t_wakeup_ns = wpt.time_ns() + self._cycle_time_ns
19        while not self._stopped:
20            wpt.sleep_until_ns(t_wakeup_ns - 400_000)
21            wpt.hotloop_until_ns(t_wakeup_ns)
22            self._main_task()
23            t_wakeup_ns += self._cycle_time_ns
24
25    def _main_task(self) -> None:
26        if self._counter % 1_000_000 == 0:
27            self._task_1ms()
28        if self._counter % 5_000_000 == 0:
29            self._task_5ms()
30        if self._counter % 10_000_000 == 0:
31            self._task_10ms()
32        self._counter += self._cycle_time_ns
33
34    def _task_1ms(self) -> None:
35        print(f"{wpt.time() - self._t0:.5f} - 1ms task")
36
37    def _task_5ms(self) -> None:
38        print(f"{wpt.time() - self._t0:.5f} - 5ms task")
39
40    def _task_10ms(self) -> None:
41        print(f"{wpt.time() - self._t0:.5f} - 10ms task")
42        self.stop()
43
44    def stop(self) -> None:
45        self._stopped = True
46
47
48class ProcessPriority(IntEnum):
49    ABOVE_NORMAL_PRIORITY_CLASS = 0x00008000
50    BELOW_NORMAL_PRIORITY_CLASS = 0x00004000
51    HIGH_PRIORITY_CLASS = 0x00000080
52    IDLE_PRIORITY_CLASS = 0x00000040
53    NORMAL_PRIORITY_CLASS = 0x00000020
54    PROCESS_MODE_BACKGROUND_BEGIN = 0x00100000
55    PROCESS_MODE_BACKGROUND_END = 0x00200000
56    REALTIME_PRIORITY_CLASS = 0x00000100
57
58
59def set_process_priority(priority: ProcessPriority) -> None:
60    pid = os.getpid()
61    handle = windll.kernel32.OpenProcess(0x0200 | 0x0400, False, pid)
62    windll.kernel32.SetPriorityClass(handle, priority)
63
64
65if __name__ == "__main__":
66    set_process_priority(ProcessPriority.HIGH_PRIORITY_CLASS)
67    rt = SoftRealtime1ms()

Output:

0.00101 - 1ms task
0.00200 - 1ms task
0.00301 - 1ms task
0.00400 - 1ms task
0.00504 - 1ms task
0.00508 - 5ms task
0.00600 - 1ms task
0.00705 - 1ms task
0.00806 - 1ms task
0.00902 - 1ms task
0.01000 - 1ms task
0.01004 - 5ms task
0.01005 - 10ms task

Note

In larger applications the garbage collector (gc) will become problematic for timing precision. Use gc.disable() if your application allows it.