Python 中的高精度时钟

2025-02-27 09:08:00
admin
原创
24
摘要:问题描述:有没有办法在 Python 中以高精度测量时间 --- 比一秒更精确?我怀疑是否有跨平台的方法可以做到这一点;我对 Unix 上的高精度时间很感兴趣,特别是在 Sun SPARC 机器上运行的 Solaris。timeit似乎能够进行高精度的时间测量,但我更愿意直接访问时间值,而不是测量代码片段所花...

问题描述:

有没有办法在 Python 中以高精度测量时间 --- 比一秒更精确?我怀疑是否有跨平台的方法可以做到这一点;我对 Unix 上的高精度时间很感兴趣,特别是在 Sun SPARC 机器上运行的 Solaris。

timeit似乎能够进行高精度的时间测量,但我更愿意直接访问时间值,而不是测量代码片段所花费的时间。


解决方案 1:

标准time.time()函数提供亚秒级精度,但该精度因平台而异。对于 Linux 和 Mac,精度为+-1 微秒或 0.001 毫秒。+-由于进程中断导致时钟实现问题,Windows 上的 Python(Python 版本低于 3.7)使用 16 毫秒精度。timeit如果您正在测量执行时间,该模块可以提供更高的分辨率。

>>> import time
>>> time.time()        #return seconds from epoch
1261367718.971009      

Python 3.7 为time模块引入了新功能,可以为更长的时间段提供更高的分辨率:

>>> import time
>>> time.time_ns()
1530228533161016309
>>> time.time_ns() / (10 ** 9) # convert to floating-point seconds
1530228544.0792289

解决方案 2:

如果选择 Python 3,则有两个选择:

  • time.perf_counter它始终使用平台上最准确的时钟。它确实包括进程之外所花费的时间。

  • time.process_time返回 CPU 时间。它不包括进程之外所花费的时间。

两者的区别可以通过以下方式展示:

from time import (
    process_time,
    perf_counter,
    sleep,
)

print(process_time())
sleep(1)
print(process_time())

print(perf_counter())
sleep(1)
print(perf_counter())

输出:

0.03125
0.03125
2.560001310720671e-07
1.0005455362793145

解决方案 3:

David 的帖子试图显示 Windows 上的时钟分辨率。他的输出让我感到困惑,所以我写了一些代码来显示time.time()我的 Windows 8 x64 笔记本电脑上的分辨率为 1 毫秒:

# measure the smallest time delta by spinning until the time changes
def measure():
    t0 = time.time()
    t1 = t0
    while t1 == t0:
        t1 = time.time()
    return (t0, t1, t1-t0)

samples = [measure() for i in range(10)]

for s in samples:
    print s

输出:

(1390455900.085, 1390455900.086, 0.0009999275207519531)
(1390455900.086, 1390455900.087, 0.0009999275207519531)
(1390455900.087, 1390455900.088, 0.0010001659393310547)
(1390455900.088, 1390455900.089, 0.0009999275207519531)
(1390455900.089, 1390455900.09, 0.0009999275207519531)
(1390455900.09, 1390455900.091, 0.0010001659393310547)
(1390455900.091, 1390455900.092, 0.0009999275207519531)
(1390455900.092, 1390455900.093, 0.0009999275207519531)
(1390455900.093, 1390455900.094, 0.0010001659393310547)
(1390455900.094, 1390455900.095, 0.0009999275207519531)

还有一种方法是对 1000 个样本的增量进行平均:

reduce( lambda a,b:a+b, [measure()[2] for i in range(1000)], 0.0) / 1000.0

连续两次运行的输出为:

0.001
0.0010009999275207519

因此time.time(),我的 Windows 8 x64 的分辨率为 1 毫秒。

类似的运行time.clock()返回 0.4 微秒的分辨率:

def measure_clock():
    t0 = time.clock()
    t1 = time.clock()
    while t1 == t0:
        t1 = time.clock()
    return (t0, t1, t1-t0)

reduce( lambda a,b:a+b, [measure_clock()[2] for i in range(1000000)] )/1000000.0

返回:

4.3571334791658954e-07

哪个是〜0.4e-06

有趣的是time.clock(),它返回自该方法首次调用以来的时间,因此如果您想要微秒分辨率的挂钟时间,您可以执行以下操作:

class HighPrecisionWallTime():
    def __init__(self,):
        self._wall_time_0 = time.time()
        self._clock_0 = time.clock()

    def sample(self,):
        dc = time.clock()-self._clock_0
        return self._wall_time_0 + dc

(一段时间后可能会出现偏差,但你可以偶尔纠正一下,例如dc > 3600每小时纠正一次)

解决方案 4:

Python 尽力使用适合您平台的最精确的时间函数来实现time.time()

/* Implement floattime() for various platforms */

static double
floattime(void)
{
    /* There are three ways to get the time:
      (1) gettimeofday() -- resolution in microseconds
      (2) ftime() -- resolution in milliseconds
      (3) time() -- resolution in seconds
      In all cases the return value is a float in seconds.
      Since on some systems (e.g. SCO ODT 3.0) gettimeofday() may
      fail, so we fall back on ftime() or time().
      Note: clock resolution does not imply clock accuracy! */
#ifdef HAVE_GETTIMEOFDAY
    {
        struct timeval t;
#ifdef GETTIMEOFDAY_NO_TZ
        if (gettimeofday(&t) == 0)
            return (double)t.tv_sec + t.tv_usec*0.000001;
#else /* !GETTIMEOFDAY_NO_TZ */
        if (gettimeofday(&t, (struct timezone *)NULL) == 0)
            return (double)t.tv_sec + t.tv_usec*0.000001;
#endif /* !GETTIMEOFDAY_NO_TZ */
    }

#endif /* !HAVE_GETTIMEOFDAY */
    {
#if defined(HAVE_FTIME)
        struct timeb t;
        ftime(&t);
        return (double)t.time + (double)t.millitm * (double)0.001;
#else /* !HAVE_FTIME */
        time_t secs;
        time(&secs);
        return (double)secs;
#endif /* !HAVE_FTIME */
    }
}

(来自http://svn.python.org/view/python/trunk/Modules/timemodule.c?revision=81756&view=markup

解决方案 5:

您还可以使用 time.clock() 它在 Unix 上计算进程所用的时间,在 Windows 上计算自第一次调用以来的时间。它比 time.time() 更精确。

这是衡量性能的常用函数。

只需拨打电话

import time
t_ = time.clock()
#Your code here
print 'Time in function', time.clock() - t_

编辑:哎呀,我错过了这个问题,因为你想知道确切的时间,而不是花费的时间......

解决方案 6:

Python 3.7 引入了 6 个具有纳秒分辨率的新时间函数,例如,time.time()您可以使用time.time_ns()来避免浮点不精确的问题:

import time
print(time.time())
# 1522915698.3436284
print(time.time_ns())
# 1522915698343660458

PEP 564中描述了这 6 个函数:

time.clock_gettime_ns(clock_id)

time.clock_settime_ns(clock_id, time:int)

time.monotonic_ns()

time.perf_counter_ns()

time.process_time_ns()

time.time_ns()

这些函数与没有 _ns 后缀的版本类似,但以 Python int 形式返回纳秒数。

解决方案 7:

time.clock()在 Windows 上有 13 个小数点,但在 Linux 上只有 2 个小数点。
time.time()在 Linux 上有 17 个小数点,在 Windows 上有 16 个小数点,但实际精度不同。

我不同意time.clock()应该在 Unix/Linux 上用于基准测试的文档。它不够精确,因此使用什么计时器取决于操作系统。

在 Linux 上,时间分辨率较高time.time()

>>> time.time(), time.time()
(1281384913.4374139, 1281384913.4374161)

然而在 Windows 上,时间函数似乎使用最后调用的号码:

>>> time.time()-int(time.time()), time.time()-int(time.time()), time.time()-time.time()
(0.9570000171661377, 0.9570000171661377, 0.0)

即使我在 Windows 中的不同行上写入调用,它仍然返回相同的值,因此实际精度较低。

import platform, platform.system()因此,在进行严肃的测量时,必须进行平台检查( ),以确定是否使用time.clock()time.time()

(在 Windows 7 和 Ubuntu 9.10 上测试,使用 Python 2.6 和 3.1)

解决方案 8:

最初的问题专门针对 Unix,但多个答案涉及 Windows,因此 Windows 上的信息具有误导性。Windows 上的默认计时器分辨率为 15.6ms,您可以在此处验证。

使用来自 cod3monk3y 的稍作修改的脚本,我可以显示 Windows 计时器分辨率默认为 ~15 毫秒。我正在使用此处提供的工具来修改分辨率。

脚本:

import time

# measure the smallest time delta by spinning until the time changes
def measure():
    t0 = time.time()
    t1 = t0
    while t1 == t0:
        t1 = time.time()
    return t1-t0

samples = [measure() for i in range(30)]

for s in samples:
    print(f'time delta: {s:.4f} seconds') 

在此处输入图片描述

在此处输入图片描述

这些结果是在运行 python 3.7 64 位的 Windows 10 Pro 64 位上收集的。

解决方案 9:

用于 Python 中的高精度计时

快速摘要

其中time.monotonic_ns(),,time.perf_counter_ns()time.time_ns(),**在Linux和Windows上都仅time.perf_counter_ns()具有亚微秒的精度。

许多人可能不理解分辨率、精度和准确度之间的区别,并可能错误地认为精确计时比实际情况更容易、更容易实现。请记住,在软件计时的背景下:

  1. 分辨率= 单位可以表示的最小时间差。例如:1 纳秒。

  2. 精度= 测量的可重复性。这是您可以重复测量的最小时间差,通常比分辨率大得多。例如:Linux 上通常为 0.070 微秒(70 纳秒),Windows 上则高达 16000 微秒(16 毫秒),或差约 23 万倍。

  3. 准确度= 测量值与真实值的接近程度。这与硬件时钟的石英晶体(或等效 RC、陶瓷或 PLL)振荡器的准确度以及校准程度有关。我们在这里不担心这一点。

使用time_monotonic_ns__get_precision.py下面的程序,以下是我在 Dell Precision 5570 Pentium i9(Linux)和 i7(Windows 11)高端 20 线程笔记本电脑上测试的结果。您的结果将根据您的硬件和操作系统而有所不同:

-------------------------------------------------------------------------------
1. time.monotonic_ns()
-------------------------------------------------------------------------------
          Resolution    Precision
          ----------    ---------
Linux:    1 ns              0.070 us +/-    0.118 us (70 ns +/- 118 ns)
Windows:  1 ns          16000.000 us +/-  486.897 us (16 ms +/- 0.487 ms)

-------------------------------------------------------------------------------
2. time.perf_counter_ns()
-------------------------------------------------------------------------------
          Resolution    Precision
          ----------    ---------
Linux:    1 ns              0.069 us +/-    0.070 us ( 69 ns +/- 70 ns)
Windows:  1 ns              0.100 us +/-    0.021 us (100 ns +/- 21 ns)

-------------------------------------------------------------------------------
3. time.time_ns()
-------------------------------------------------------------------------------
          Resolution    Precision
          ----------    ---------
Linux:    1 ns              0.074 us +/-    0.226 us (74 ns +/- 226 ns)
Windows:  1 ns          10134.354 us +/- 5201.053 us (10.134 ms +/- 5.201 ms)

请注意,尽管所有 3 个函数都具有 1 纳秒的分辨率,但**在 Linux 和 Windows 上都只time.perf_counter_ns()具有亚微秒的精度。其他两个函数仅在 Linux 上具有亚微秒的精度,但在 Windows 上却很糟糕(精度低)。

细节

  1. Python 3.7 或更高版本


如果使用 Python 3.7 或更高版本,请使用此处的现代跨平台time模块函数,如time.monotonic_ns()time.perf_counter_ns()time.time_ns()https://docs.python.org/3/library/time.html#time.monotonic_ns

import time

# For Unix, Linux, Windows, etc.
time_ns = time.monotonic_ns()     # note: unspecified epoch
time_ns = time.perf_counter_ns()  # **best precision**
time_ns = time.time_ns()          # known epoch

# Unix or Linux only
time_ns = time.clock_gettime_ns()

# etc. etc. There are others. See the link above.

另请参阅我 2016 年的另一个回答中的这条注释:如何在 Python 中获取毫秒和微秒分辨率的时间戳?:

您也可以time.clock_gettime_ns()在 Unix 或 Linux 系统上尝试。根据其名称,它似乎调用了底层C 函数,我在 C 函数(此处的答案)和 C Unix/Linux 库(此处)中clock_gettime()使用该函数: timinglib.c。nanos()


作为快速测试,您可以运行以下命令来了解特定硬件和操作系统的最低分辨率。我已经在 Linux 和 Windows 上测试并运行了此操作:

来自我的eRCaGuy_hello_world repo 的python/time_monotonic_ns__get_precision.py

#!/usr/bin/env python3

import os
import pandas as pd
import time

SAMPLE_SIZE_DEFAULT = 20000
# For cases where Windows may have really crappy 16ms precision, we need a
# significantly larger sample size.
SAMPLE_SIZE_MIN_FOR_WINDOWS = 20000000
DEBUG = False  # Set to True to enable debug prints

def debug_print(*args, **kwargs):
    if DEBUG:
        print(*args, **kwargs)

def print_bar():
    debug_print("="*56, "
")

def process_timestamps(timestamps_ns, output_stats_header_str):
    """
    Process the timestamps list to determine the time precision of the system.
    """

    # Create a pandas DataFrame for efficient analysis of large datasets
    df = pd.DataFrame({"timestamp_ns": timestamps_ns}, dtype='int64')
    debug_print(f"df original:
{df}")
    print_bar()

    # Remove duplicate timestamps. On Linux, there won't be any, because it has
    # sub-microsecond precision, but on Windows, the dataset may be mostly
    # duplicates because repeated calls to `time.monotonic_ns()` may return the
    # same value if called in quick succession.
    df.drop_duplicates(inplace=True)
    debug_print(f"df no duplicates:
{df}")
    print_bar()
    if len(df) < 2:
        print("Error: not enough data to calculate time precision. Try 
"
              "increasing `SAMPLE_SIZE` by a factor of 10, and try again.")
        exit(1)

    # Now calculate the time differences between the timestamps.
    df["previous_timestamp_ns"] = df["timestamp_ns"].shift(1)
    df = df.dropna()  # remove NaN row
    df["previous_timestamp_ns"] = df["previous_timestamp_ns"].astype('int64')
    df["delta_time_us"] = (
        df["timestamp_ns"] - df["previous_timestamp_ns"]) / 1e3
    debug_print(f"df:
{df}")
    print_bar()

    # Output statistics
    
    mean = df["delta_time_us"].mean()
    median = df["delta_time_us"].median()
    mode = df["delta_time_us"].mode()[0]
    stdev = df["delta_time_us"].std()

    print(f">>>>>>>>>> {output_stats_header_str} <<<<<<<<<<")
    print(f"Mean:   {mean:.3f} us")
    print(f"Median: {median:.3f} us")
    print(f"Mode:   {mode:.3f} us")
    print(f"Stdev:  {stdev:.3f} us")
    print(f"FINAL ANSWER: time precision on this system: "
        + f"{median:.3f} +/- {stdev:.3f} us
")

# =============================================================================
# 1. Test `time.monotonic_ns()`
# =============================================================================

SAMPLE_SIZE = SAMPLE_SIZE_DEFAULT
if os.name == 'nt':
    # The OS is Windows
    if SAMPLE_SIZE < SAMPLE_SIZE_MIN_FOR_WINDOWS:
        SAMPLE_SIZE = SAMPLE_SIZE_MIN_FOR_WINDOWS
        print(f"Detected: running on Windows. Using a larger SAMPLE_SIZE of "
            f"{SAMPLE_SIZE}.
")

# Gather timestamps with zero delays between them
# - preallocated list, so that no dynamic memory allocation will happen in the
#   loop below
timestamps_ns = [None]*SAMPLE_SIZE
for i in range(len(timestamps_ns)):
    timestamps_ns[i] = time.monotonic_ns()

process_timestamps(timestamps_ns, "1. time.monotonic_ns()")

# =============================================================================
# 2. Test `time.perf_counter_ns()`
# =============================================================================

SAMPLE_SIZE = SAMPLE_SIZE_DEFAULT

timestamps_ns = [None]*SAMPLE_SIZE
for i in range(len(timestamps_ns)):
    timestamps_ns[i] = time.perf_counter_ns()

process_timestamps(timestamps_ns, "2. time.perf_counter_ns()")

# =============================================================================
# 3. Test `time.time_ns()`
# =============================================================================

SAMPLE_SIZE = SAMPLE_SIZE_DEFAULT
if os.name == 'nt':
    # The OS is Windows
    if SAMPLE_SIZE < SAMPLE_SIZE_MIN_FOR_WINDOWS:
        SAMPLE_SIZE = SAMPLE_SIZE_MIN_FOR_WINDOWS
        print(f"Detected: running on Windows. Using a larger SAMPLE_SIZE of "
            f"{SAMPLE_SIZE}.
")

timestamps_ns = [None]*SAMPLE_SIZE
for i in range(len(timestamps_ns)):
    timestamps_ns[i] = time.time_ns()

process_timestamps(timestamps_ns, "3. time.time_ns()")

这是我在几台高端 Dell Precision 5570 Pentium i9(Linux)和 i7(Windows 11)20 线程笔记本电脑上运行它时的运行和输出。

Linux Ubuntu 22.04上(python3 --version显示Python 3.10.12):

eRCaGuy_hello_world$ time python/time_monotonic_ns__get_precision.py 
>>>>>>>>>> 1. time.monotonic_ns() <<<<<<<<<<
Mean:   0.081 us
Median: 0.070 us
Mode:   0.070 us
Stdev:  0.118 us
FINAL ANSWER: time precision on this system: 0.070 +/- 0.118 us

>>>>>>>>>> 2. time.perf_counter_ns() <<<<<<<<<<
Mean:   0.076 us
Median: 0.069 us
Mode:   0.068 us
Stdev:  0.070 us
FINAL ANSWER: time precision on this system: 0.069 +/- 0.070 us

>>>>>>>>>> 3. time.time_ns() <<<<<<<<<<
Mean:   0.080 us
Median: 0.074 us
Mode:   -0.030 us
Stdev:  0.226 us
FINAL ANSWER: time precision on this system: 0.074 +/- 0.226 us


real    0m0.264s
user    0m0.802s
sys 0m1.124s

Windows 11上(python --version显示Python 3.12.1):

eRCaGuy_hello_world$ time python/time_monotonic_ns__get_precision.py
Detected: running on Windows. Using a larger SAMPLE_SIZE of 20000000.

>>>>>>>>>> 1. time.monotonic_ns() <<<<<<<<<<
Mean:   15625.000 us
Median: 16000.000 us
Mode:   16000.000 us
Stdev:  486.897 us
FINAL ANSWER: time precision on this system: 16000.000 +/- 486.897 us

>>>>>>>>>> 2. time.perf_counter_ns() <<<<<<<<<<
Mean:   0.101 us
Median: 0.100 us
Mode:   0.100 us
Stdev:  0.021 us
FINAL ANSWER: time precision on this system: 0.100 +/- 0.021 us

Detected: running on Windows. Using a larger SAMPLE_SIZE of 20000000.

>>>>>>>>>> 3. time.time_ns() <<<<<<<<<<
Mean:   9639.436 us
Median: 10134.354 us
Mode:   610.144 us
Stdev:  5201.053 us
FINAL ANSWER: time precision on this system: 10134.354 +/- 5201.053 us


real    0m8.301s
user    0m0.000s
sys     0m0.000s

每种情况下的中值最能代表您系统所期望的典型分辨率,因为使用中值可以同时消除时间抖动和异常值(与平均值不同,平均值可以消除时间抖动但不消除异常值)。

这充分证明只有该time.perf_counter_ns()函数在 Windows 和 Linux 上都具有亚微秒的分辨率精度,这正是我最需要知道的。

未指定时代:

请注意,使用time.monotonic()或时time.monotonic_ns(),官方文档说:

返回值的参考点未定义,因此只有两次调用结果之间的差异才有效。

因此,如果您需要绝对日期时间类型的时间戳而不是精度相对时间戳(绝对日期时间包含年、月、日等信息),那么您应该考虑使用datetime。请参阅此处的答案、下面的评论以及此处的官方文档,特别是此处的官方datetime文档。以下是如何使用该模块获取时间戳:datetime.now()

from datetime import datetime

now_datetime_object = datetime.now()

但是,不要期望它具有 的分辨率、精度和单调性time.clock_gettime_ns()。因此,对于计时小差异或进行精确计时工作,time.clock_gettime_ns()最好选择 。

另一个选项是time.time()-- 也不能保证“精度优于 1 秒”。您可以使用time.localtime()或将其转换回日期时间time.gmtime()。请参阅此处。以下是使用方法:

>>> import time
>>> time.time()
1691442858.8543699
>>> time.localtime(time.time())
time.struct_time(tm_year=2023, tm_mon=8, tm_mday=7, tm_hour=14, tm_min=14, tm_sec=36, tm_wday=0, tm_yday=219, tm_isdst=0)

或者,甚至更好time.time_ns()::

>>> import time
>>> time.time_ns()
1691443244384978570
>>> time.localtime(time.time_ns()/1e9)
time.struct_time(tm_year=2023, tm_mon=8, tm_mday=7, tm_hour=14, tm_min=20, tm_sec=57, tm_wday=0, tm_yday=219, tm_isdst=0)
>>> time.time_ns()/1e9
1691443263.0889063
  1. Python 3.3 或更高版本


Windows 上,在 Python 3.3 或更高版本中,您可以使用time.perf_counter(),如 @ereOn 在这里所示。请参阅:https ://docs.python.org/3/library/time.html#time.perf_counter 。这提供了大约0.5us分辨率的时间戳,以浮点秒为单位。例如:

import time

# For Python 3.3 or later
time_sec = time.perf_counter()  # Windows only, I think
# or on Unix or Linux (I think only those)
time_sec = time.monotonic()
  1. Python 3.3 之前的版本(例如:Python 3.0、3.1、3.2)或更高版本


概括:

请参阅我 2016 年在此处的其他答案,了解 Windows 和 Linux 中 0.5 us 分辨率时间戳或更佳时间戳,以及 Python 3.0、3.2 或 3.2 甚至更早的版本!我们通过使用 Python 中的模块调用 C 或 C++共享对象库(Windows 上的 .dll 或 Unix 或 Linux 上的 .so)来实现此目的ctypes

我提供以下功能:

millis()
micros()
delay()
delayMicroseconds()

GS_timing.py从我的eRCaGuy_PyTime repo下载,然后执行以下操作:

import GS_timing

time_ms = GS_timing.millis()
time_us = GS_timing.micros()
GS_timing.delay(10)                # delay 10 ms
GS_timing.delayMicroseconds(10000) # delay 10000 us

细节:

2016 年,我使用 Python 3.0 或 3.1 在 Raspberry Pi 上开发一个嵌入式项目,我也经常在 Windows 上测试和运行该项目。我需要纳秒级的分辨率来对超声波传感器进行精确计时。当时的 Python 语言没有提供这种分辨率,也没有对这个问题的答案,所以我在这里提出了一个单独的问答:如何在 Python 中获取毫秒和微秒级分辨率的时间戳?我在当时的问题中说道:

在提出这个问题之前,我读过其他答案,但它们依赖于time模块,在 Python 3.3 之前,该模块根本没有任何类型的保证分辨率。它的分辨率到处都是。这里得票最多的答案引用了 Windows 分辨率(使用他们的答案)16 毫秒,这比我在这里提供的答案(0.5 微秒分辨率)差32000 倍。同样,我需要1 毫秒1 微秒(或类似)的分辨率,而不是 16000 微秒的分辨率。

,我再说一遍:2016 年 7 月 12 日这里没有一个答案Python 3.1中对Windows的分辨率优于16 毫秒。因此,我想出了这个答案,它在 Windows 和 Linux 的 Python 3.3之前的版本中具有 0.5us 或更好的分辨率。如果您需要类似的东西用于旧版本的 Python,或者如果您只是想学习如何使用该在 Python 中调用 C 或 C++ 动态库(Windows 中的 .dll“动态链接库”文件,或 Unix 或 Linux 中的 .so“共享对象”库文件),请参阅我的其他答案。ctypes

参考

  1. 我的问答:如何在 Python 中获取毫秒和微秒分辨率的时间戳?

  2. 我的回答:如何DataFrame在不迭代的情况下迭代 Pandas

  3. https://docs.python.org/3/library/time.html

解决方案 10:

tiho 在 2014 年 3 月 27 日 17:21 留下的评论值得作为自己的答案:

为了避免特定于平台的代码,请使用 timeit.default_timer()

解决方案 11:

我观察到 Windows 10 专业版和教育版之间 time.time() 的分辨率不同。

在 Windows 10 专业版计算机上,分辨率为 1 毫秒。在 Windows 10 教育版计算机上,分辨率为 16 毫秒。

幸运的是,有一个工具可以提高 Windows 中 Python 的时间分辨率:
https://vvvv.org/contribution/windows-system-timer-tool

使用此工具,无论 Windows 版本如何,我都能实现 1 毫秒的分辨率。您需要在执行 Python 代码时保持它运行。

解决方案 12:

对于那些停留在 Windows(版本 >= Server 2012 或 Win8)和 Python 2.7 上的人来说,

import ctypes

class FILETIME(ctypes.Structure):
    _fields_ = [("dwLowDateTime", ctypes.c_uint),
                ("dwHighDateTime", ctypes.c_uint)]

def time():
    """Accurate version of time.time() for windows, return UTC time in term of seconds since 01/01/1601
"""
    file_time = FILETIME()
    ctypes.windll.kernel32.GetSystemTimePreciseAsFileTime(ctypes.byref(file_time))
    return (file_time.dwLowDateTime + (file_time.dwHighDateTime << 32)) / 1.0e7

GetSystemTimePreciseAsFileTime 函数

解决方案 13:

在同一个 win10 操作系统上使用“两种不同的方法”似乎存在大约“500 纳秒”的时间差。如果您关心纳秒精度,请查看下面的代码。

代码的修改基于用户cod3monk3y和的代码Kevin S

操作系统:python 3.7.3 (default, date, time) [MSC v.1915 64 bit (AMD64)]

def measure1(mean):
    for i in range(1, my_range+1):
        x = time.time()
        
        td = x- samples1[i-1][2]
        if i-1 == 0:
            td = 0
        td = f'{td:.6f}'
        samples1.append((i, td, x))
        mean += float(td)
        print (mean)
        sys.stdout.flush()
        time.sleep(0.001)
    
    mean = mean/my_range
    
    return mean

def measure2(nr):
    t0 = time.time()
    t1 = t0
    while t1 == t0:
        t1 = time.time()
    td = t1-t0
    td = f'{td:.6f}'
    return (nr, td, t1, t0)

samples1 = [(0, 0, 0)]
my_range = 10
mean1    = 0.0
mean2    = 0.0

mean1 = measure1(mean1)

for i in samples1: print (i)

print ('...

')

samples2 = [measure2(i) for i in range(11)]

for s in samples2:
    #print(f'time delta: {s:.4f} seconds')
    mean2 += float(s[1])
    print (s)
    
mean2 = mean2/my_range

print ('
Mean1 : ' f'{mean1:.6f}')
print ('Mean2 : ' f'{mean2:.6f}')

测量1的结果:

nr, td, t0
(0, 0, 0)
(1, '0.000000', 1562929696.617988)
(2, '0.002000', 1562929696.6199884)
(3, '0.001001', 1562929696.620989)
(4, '0.001001', 1562929696.62199)
(5, '0.001001', 1562929696.6229906)
(6, '0.001001', 1562929696.6239917)
(7, '0.001001', 1562929696.6249924)
(8, '0.001000', 1562929696.6259928)
(9, '0.001001', 1562929696.6269937)
(10, '0.001001', 1562929696.6279945)
...

测量2的结果:

nr, td , t1, t0
(0, '0.000500', 1562929696.6294951, 1562929696.6289947)
(1, '0.000501', 1562929696.6299958, 1562929696.6294951)
(2, '0.000500', 1562929696.6304958, 1562929696.6299958)
(3, '0.000500', 1562929696.6309962, 1562929696.6304958)
(4, '0.000500', 1562929696.6314962, 1562929696.6309962)
(5, '0.000500', 1562929696.6319966, 1562929696.6314962)
(6, '0.000500', 1562929696.632497, 1562929696.6319966)
(7, '0.000500', 1562929696.6329975, 1562929696.632497)
(8, '0.000500', 1562929696.633498, 1562929696.6329975)
(9, '0.000500', 1562929696.6339984, 1562929696.633498)
(10, '0.000500', 1562929696.6344984, 1562929696.6339984)

最终结果:

平均值1:0.001001#(测量1函数)

平均值2:0.000550#(measure2函数)

解决方案 14:

这是适用于 Windows 的 Python 3 解决方案,基于Cyber​​Snoopy上面发布的答案(使用GetSystemTimePreciseAsFileTime)。我们从jfs借用了一些代码

Python datetime.utcnow() 返回错误的日期时间

并获取以微秒为单位的精确时间戳(Unix 时间)

#! python3
import ctypes.wintypes

def utcnow_microseconds():
    system_time = ctypes.wintypes.FILETIME()
    #system call used by time.time()
    #ctypes.windll.kernel32.GetSystemTimeAsFileTime(ctypes.byref(system_time))
    #getting high precision:
    ctypes.windll.kernel32.GetSystemTimePreciseAsFileTime(ctypes.byref(system_time))
    large = (system_time.dwHighDateTime << 32) + system_time.dwLowDateTime
    return large // 10 - 11644473600000000

for ii in range(5):
    print(utcnow_microseconds()*1e-6)

参考

https://learn.microsoft.com/en-us/windows/win32/sysinfo/time-functions

https://learn.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getsystemtimepreciseasfiletime

https://support.microsoft.com/en-us/help/167296/how-to-convert-a-unix-time-t-to-a-win32-filetime-or-systemtime

解决方案 15:

def start(self):
    sec_arg = 10.0
    cptr = 0
    time_start = time.time()
    time_init = time.time()
    while True:
        cptr += 1
        time_start = time.time()
        time.sleep(((time_init + (sec_arg * cptr)) - time_start ))

        # AND YOUR CODE .......
        t00 = threading.Thread(name='thread_request', target=self.send_request, args=([]))
        t00.start()
相关推荐
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1289  
  IPD(Integrated Product Development)流程作为一种先进的产品开发管理模式,在众多企业中得到了广泛应用。其中,技术评审(TR,Technical Review)环节至关重要,它不仅是对技术方案的评估,更是激发创新思维、推动产品创新的关键节点。深入理解TR在IPD流程中的创新思维及其应用实践...
IPD流程中TR   9  
  IPD(Integrated Product Development)产品开发流程作为一种先进的产品开发管理模式,在众多企业中得到了广泛应用。它打破了传统产品开发过程中部门之间的壁垒,将市场、研发、生产、销售等各个环节有机整合在一起,形成一个高效协同的整体。通过这种方式,企业能够更快速、更精准地开发出满足市场需求的产品...
IPD管理流程   11  
  IPD(Integrated Product Development)流程作为一种先进的产品开发管理模式,在众多企业中得到了广泛应用。其中,技术评审(TR,Technical Review)环节在整个IPD流程里占据着关键位置,对项目的成功有着深远影响。深入探讨TR与项目成功的关系,有助于企业更好地运用IPD流程,提升...
IPD项目管理   8  
  IPD研发管理体系旨在打破部门墙,实现跨部门协同,确保产品开发以市场和客户需求为导向,高效、高质量地推出满足市场需求的产品。在这一体系下,产品创新可拆解为三个关键步骤,它们环环相扣,共同推动企业的产品不断迭代升级,在激烈的市场竞争中占据优势。这三个步骤分别聚焦于洞察市场机会、规划产品战略以及执行开发与验证,每一步都蕴含...
IPD框架   10  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用