为什么 datetime.utcnow 的行为与我对 freezegun 的预期不同?
Why does datetime.utcnow not behave as I'd expect with freezegun?
我注意到一些我不明白的东西,我想知道是否有人可以阐明它。
简而言之:如果
x = datetime.datetime.utcnow
和
y = lambda: datetime.datetime.utcnow()
我希望 x()
和 y()
的行为始终相同。但是,当涉及 freezegun 时,情况显然并非如此 - 它冻结 y
而不是 x
,我想知道为什么。 (无论如何,如果 x
和 y
是在 freezegun 上下文之外定义的,则为真;在这样的上下文中,它们的行为似乎相同。)
示例:
from datetime import datetime
import freezegun
# I'd expect these two to behave the same, always.
x = datetime.utcnow
y = lambda: datetime.utcnow()
with freezegun.freeze_time('2019-01-02 03:04:05'):
# Here their behaviours diverge
print('Time from x:', x())
print('Time from y:', y())
# This behaves as I'd expect, however.
z = datetime.utcnow
print('Time from z:', z())))
结果:
Time from x: 2019-10-18 12:21:37.508590
Time from y: 2019-01-02 03:04:05
Time from z: 2019-01-02 03:04:05
这里 Time from x
是现在 运行 的时间,即它不受 freezegun 的控制。
任何人都可以阐明这一点吗?这只是 freezegun 的一些奇怪之处,或者当我假设 x
和 y
应该总是等价时,我是否误解了关于 python 的更基本的东西?我看到 utcnow
是一个绑定的 class 方法,但我不明白为什么这会暗示这种行为。
后记:time.time
不是这样的
看看 utcnow()
's source 它基本上只是 time.time()
的包装器 — 但 time.time
和 lambda: time.time()
不 分歧以这种方式......所以我猜这 does 与 utcnow()
being a bound class methiod有关 - 但我不知道是什么.
import time
import freezegun
r = time.time
s = lambda: time.time()
print('Time outside freezegun:', time.time())
with freezegun.freeze_time('2019-01-02 03:04:05'):
print('Time from r:', r())
print('Time from s:', s())
给出:
Time outside freezegun: 1571401765.2612312
Time from r: 1546398245.0
Time from s: 1546398245.0
正在播放的版本
$ python --version
Python 3.7.3
$ pip list | grep freezegun
freezegun 0.3.12
So I'm guessing this does have something to do with utcnow() being a bound class methiod — but I don't know what.
看来你的直觉是正确的。 Freezegun 不修补 datetime
class 的个别方法 - 而是 it replaces the class entirely 用它自己的 FakeDatetime
class.
通过做作业:
x = datetime.utcnow
x 存储对原始 utcnow()
方法的引用,即使在 freezegun.freeze_time()
上下文管理器中也保持不变。
另一方面,lambda: datetime.utcnow()
在 datetime
class 上调用 utcnow()
,它在当前上下文中可用,并且 FakeDatetime
由 freezegun.freeze_time()
.
time.time()
是 patched by freezegun with fake_time()
. Freezegun even searches through loaded modules and patches variables 存储对 time.time()
的引用,但它仅限于模块变量,例如它不检查内部列表:
import time
import freezegun
r = [time.time]
with freezegun.freeze_time('2019-01-02 03:04:05'):
print('Time inside freezegun:', time.time())
time_inside_list = r[0]
print('Time from list:', time_inside_list())
输出:
Time inside freezegun: 1546398245.0
Time from list: 1571669871.8807676
Bonus:如果 freezegun 如此细致地查找存储在模块变量中的 time.time()
引用,为什么它不修补 time.time()
在 datetime.utcnow()
?
在搜索 sys.modules
时 deliberately omits datetime
和 time
模块不覆盖源函数,作为副作用 time.time
在 datetime
模块保持未打补丁。
我注意到一些我不明白的东西,我想知道是否有人可以阐明它。
简而言之:如果
x = datetime.datetime.utcnow
和
y = lambda: datetime.datetime.utcnow()
我希望 x()
和 y()
的行为始终相同。但是,当涉及 freezegun 时,情况显然并非如此 - 它冻结 y
而不是 x
,我想知道为什么。 (无论如何,如果 x
和 y
是在 freezegun 上下文之外定义的,则为真;在这样的上下文中,它们的行为似乎相同。)
示例:
from datetime import datetime
import freezegun
# I'd expect these two to behave the same, always.
x = datetime.utcnow
y = lambda: datetime.utcnow()
with freezegun.freeze_time('2019-01-02 03:04:05'):
# Here their behaviours diverge
print('Time from x:', x())
print('Time from y:', y())
# This behaves as I'd expect, however.
z = datetime.utcnow
print('Time from z:', z())))
结果:
Time from x: 2019-10-18 12:21:37.508590
Time from y: 2019-01-02 03:04:05
Time from z: 2019-01-02 03:04:05
这里 Time from x
是现在 运行 的时间,即它不受 freezegun 的控制。
任何人都可以阐明这一点吗?这只是 freezegun 的一些奇怪之处,或者当我假设 x
和 y
应该总是等价时,我是否误解了关于 python 的更基本的东西?我看到 utcnow
是一个绑定的 class 方法,但我不明白为什么这会暗示这种行为。
后记:time.time
不是这样的
看看 utcnow()
's source 它基本上只是 time.time()
的包装器 — 但 time.time
和 lambda: time.time()
不 分歧以这种方式......所以我猜这 does 与 utcnow()
being a bound class methiod有关 - 但我不知道是什么.
import time
import freezegun
r = time.time
s = lambda: time.time()
print('Time outside freezegun:', time.time())
with freezegun.freeze_time('2019-01-02 03:04:05'):
print('Time from r:', r())
print('Time from s:', s())
给出:
Time outside freezegun: 1571401765.2612312
Time from r: 1546398245.0
Time from s: 1546398245.0
正在播放的版本
$ python --version
Python 3.7.3
$ pip list | grep freezegun
freezegun 0.3.12
So I'm guessing this does have something to do with utcnow() being a bound class methiod — but I don't know what.
看来你的直觉是正确的。 Freezegun 不修补 datetime
class 的个别方法 - 而是 it replaces the class entirely 用它自己的 FakeDatetime
class.
通过做作业:
x = datetime.utcnow
x 存储对原始 utcnow()
方法的引用,即使在 freezegun.freeze_time()
上下文管理器中也保持不变。
另一方面,lambda: datetime.utcnow()
在 datetime
class 上调用 utcnow()
,它在当前上下文中可用,并且 FakeDatetime
由 freezegun.freeze_time()
.
time.time()
是 patched by freezegun with fake_time()
. Freezegun even searches through loaded modules and patches variables 存储对 time.time()
的引用,但它仅限于模块变量,例如它不检查内部列表:
import time
import freezegun
r = [time.time]
with freezegun.freeze_time('2019-01-02 03:04:05'):
print('Time inside freezegun:', time.time())
time_inside_list = r[0]
print('Time from list:', time_inside_list())
输出:
Time inside freezegun: 1546398245.0
Time from list: 1571669871.8807676
Bonus:如果 freezegun 如此细致地查找存储在模块变量中的 time.time()
引用,为什么它不修补 time.time()
在 datetime.utcnow()
?
在搜索 sys.modules
时 deliberately omits datetime
和 time
模块不覆盖源函数,作为副作用 time.time
在 datetime
模块保持未打补丁。