为了账号安全,请及时绑定邮箱和手机立即绑定

为什么 datetime.utcnow 的行为不像我对 freezegun 的预期那样?

为什么 datetime.utcnow 的行为不像我对 freezegun 的预期那样?

LEATH 2022-06-28 15:28:37
我注意到一些我不明白的东西,我想知道是否有人可以阐明它。简而言之:如果x = datetime.datetime.utcnow和y = lambda: datetime.datetime.utcnow()我希望x()并且y()总是表现得一样。然而,当 freezegun 参与时显然不是这种情况 - 它冻结y但没有x,我想知道为什么。(无论如何,如果x并且y在 freezegun 上下文之外定义,这是真的;在这样的上下文中,它们的行为似乎相同。)例子:from datetime import datetimeimport freezegun# I'd expect these two to behave the same, always.x = datetime.utcnowy = 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.508590Time from y: 2019-01-02 03:04:05Time from z: 2019-01-02 03:04:05这Time from x是运行时的时间,即它不受 freezegun 的控制。任何人都可以对此有所了解吗?这只是 freezegun 的一些奇怪之处,或者当我假设x并且y应该始终等价时,我是否误解了关于 python 的更基本的东西?我看到这utcnow是一个绑定的类方法,但我不明白为什么这会暗示这种行为。后记:time.time不这样做查看utcnow()'s source它基本上只是一个包装器-time.time()但不要以这种方式发散...所以我猜这确实与绑定类方法有关-但我不知道是什么。time.timelambda: time.time() utcnow()import timeimport freezegunr = time.times = 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.2612312Time from r: 1546398245.0Time from s: 1546398245.0游戏中的版本$ python --versionPython 3.7.3$ pip list | grep freezegunfreezegun               0.3.12
查看完整描述

1 回答

?
牛魔王的故事

TA贡献1830条经验 获得超3个赞

所以我猜这确实与 utcnow() 是一个绑定类方法有关——但我不知道是什么。


看起来你的直觉是正确的。Freezegun 不会修补datetime类的单个方法 - 相反,它会用自己的类完全替换FakeDatetime该类。


通过做作业:


x = datetime.utcnow

x 存储对原始utcnow()方法的引用,即使在freezegun.freeze_time()上下文管理器中也保持不变。


另一方面,lambda: datetime.utcnow()调用当前上下文中可用的类utcnow(),并由.datetimeFakeDatetimefreezegun.freeze_time()


time.time()由freezegunfake_time()修补。Freezegun 甚至搜索已加载的模块并修补存储对 的引用的变量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

奖励:如果 freezegun 如此细致地查找time.time()存储在模块变量中的引用,为什么它不修补time.time()内部使用的datetime.utcnow()?


在搜索sys.modules它时故意省略 datetime和模块不覆盖源函数,并且作为在模块中导入time的副作用保持不修补。time.timedatetime


查看完整回答
反对 回复 2022-06-28
  • 1 回答
  • 0 关注
  • 90 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信