Eug*_*ash 7 python macos python-datetime docker macos-monterey
考虑这个简单的 Python 脚本:
$ cat test_utc.py
from datetime import datetime
for i in range(10_000_000):
first = datetime.utcnow()
second = datetime.utcnow()
assert first <= second, f"{first=} {second=} {i=}"
Run Code Online (Sandbox Code Playgroud)
当我从 shell 运行它时,就像python test_utc.py它完成时没有错误一样,正如预期的那样。但是,当我在 Docker 容器中运行它时,断言失败:
$ docker run -it --rm -v "$PWD":/code -w /code python:3.10.4 python test_utc.py
Traceback (most recent call last):
File "/code/test_utc.py", line 7, in <module>
assert first <= second, f"{first=} {second=} {i=}"
AssertionError: first=datetime.datetime(2022, 5, 24, 19, 5, 1, 861308) second=datetime.datetime(2022, 5, 24, 19, 5, 1, 818270) i=1818860
Run Code Online (Sandbox Code Playgroud)
这怎么可能?
PS 一位同事报告说,增加范围参数也会100_000_000使其在 Mac 上的 shell 中失败(但对我来说不是)。
utcnow指的是now指指的today是fromtimestamp指指的time是指:
\n\n虽然此函数通常返回不递减的值,但如果系统时钟在两次调用之间被调回,则它可能返回比前一次调用更低的值。
\n
该utcnow代码还显示了它的用法time:
def utcnow(cls):\n "Construct a UTC datetime from time.time()."\n t = _time.time()\n return cls.utcfromtimestamp(t)\nRun Code Online (Sandbox Code Playgroud)\n这种系统时钟更新也是monotonic存在的原因,它说:
\n\n返回单调时钟的值(以小数秒为单位),即不能倒退的时钟。时钟不受系统时钟更新的影响。
\n
并且utcnow没有这样的保证。
您的计算机没有完美的时钟,它时不时地通过互联网与更准确的时钟同步,可能会向后调整它。请参阅此处的示例答案。
\n看起来 Docker 使情况变得更糟,请参阅Docker 博客中的解决 Docker Desktop for Mac 中的时间漂移的示例。摘抄:
\n\n\nmacOS 没有\xe2\x80\x99t 本机容器支持。辅助虚拟机有自己的内部时钟,与主机\xe2\x80\x99s 时钟分开。当两个时钟偏离时,依赖时间或文件时间戳的命令可能会突然开始表现不同
\n
最后,您可以增加在发生向后更新时捕获向后更新的机会。如果一个不是发生在 gettingfirst和之间,second而是发生在second和 next之间first,你就会错过它!下面的代码修复了这个问题,并且还进行了微优化(包括删除中间人utcnow),因此它检查得更快/更频繁:
import time\nfrom itertools import repeat\n\ndef function():\n n = 10_000_000\n reps = repeat(1, n)\n now = time.time\n first = now()\n for _ in reps:\n second = now()\n assert first <= second, f"{first=} {second=} i={n - sum(reps)}"\n first = second\nfunction()\nRun Code Online (Sandbox Code Playgroud)\n
| 归档时间: |
|
| 查看次数: |
516 次 |
| 最近记录: |