You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python unittest中mock datetime内部_time.time报错:module 'datetime' has no attribute '_time' 问题排查

Python unittest中mock datetime内部_time.time报错:module 'datetime' has no attribute '_time' 问题排查

嗨,我来帮你捋捋这个问题,你踩的这个坑其实挺常见的,很多人看了datetime的纯Python源码后都会犯这个错。

首先,你报错的核心原因是:你看到的是CPython仓库里纯Python版本的datetime.py源码,但实际运行Python时,默认加载的是用C语言实现的datetime扩展模块。这个C版本里根本没有_time这个属性——纯Python版里的import time as _time是Python层的导入逻辑,而C实现的datetime模块是直接调用底层C的时间函数,不会有这个Python层面的别名。所以你尝试访问datetime._time的时候,自然会提示找不到这个属性。

那该怎么解决呢?给你两个实用的方案,根据你的需求选:

方案一:直接mock datetime.datetime.utcnow(推荐)

其实我们最终关心的是utcnow()的返回值,完全没必要去mock它内部调用的time.time(),直接mock这个方法本身更简单可靠,也不会受datetime模块实现版本的影响。

修改你的代码如下:

def test1(self):
    # 模拟utcnow返回1970-01-01 UTC时间
    mock_utcnow = Mock(return_value=datetime.datetime(1970, 1, 1, tzinfo=datetime.timezone.utc))
    with patch('datetime.datetime.utcnow', wraps=mock_utcnow):
        print(time.time())  # 如果不需要mock这个可以保留真实值,要mock的话再额外patch time.time
        print(datetime.datetime.utcnow())  # 会输出1970-01-01 00:00:00+00:00

方案二:同时mock全局的time.time和utcnow(如果需要联动)

如果你确实需要让time.time()和utcnow()的返回值保持一致(比如都基于同一个时间戳),可以先mocktime.time,再基于这个时间戳生成对应的utc时间来mockutcnow:

def test1(self):
    target_timestamp = 0  # 对应1970-01-01
    time_patch = Mock(return_value=target_timestamp)
    utcnow_patch = Mock(return_value=datetime.datetime.fromtimestamp(target_timestamp, datetime.timezone.utc))
    
    with patch('time.time', wraps=time_patch), patch('datetime.datetime.utcnow', wraps=utcnow_patch):
        print(time.time())  # 输出0
        print(datetime.datetime.utcnow())  # 输出1970-01-01 00:00:00+00:00

这里要注意:单独mocktime.time()不会影响C版本datetime的utcnow(),因为C版本是直接调用系统时间,不会经过Python的time.time()函数,所以必须同时mockutcnow()才能达到预期效果。

总结一下,别去碰datetime模块内部的私有导入属性,直接mock你关心的公开方法是最稳妥的做法,也能避免因为模块实现版本不同带来的问题。

备注:内容来源于stack exchange,提问作者deiviz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.21 09:48:10