我使用带有 S3 的 Django 作为文件存储(使用 boto3/botocore 库)。我有一个创建一些 Django 实例的“管理”命令——我使用 freezegun,所以这些实例似乎是在过去创建的。但是,其中一些模型包含正在保存到 S3 的文件 - 这会引发一些异常:
...
File "/home/rado/.virtualenvs/twisto/lib/python3.6/site-packages/botocore/client.py", line 314, in _api_call
return self._make_api_call(operation_name, kwargs)
File "/home/rado/.virtualenvs/twisto/lib/python3.6/site-packages/botocore/client.py", line 612, in _make_api_call
raise error_class(parsed_response, operation_name)
botocore.exceptions.ClientError: An error occurred (RequestTimeTooSkewed) when calling the ListObjectsV2 operation: The difference between the request time and the current time is too large.
这是由于botocore.auth
模块中的一些身份验证代码检查时间差异。我尝试使用ignore
参数 ( freeze_time(datetime_in_past, ignore=['botocore'])
) 来解决这个问题,但它没有帮助,botocore.auth
仍然使用FakeDatetime
(我使用带有断点的调试器来查明问题)。
我试图用一个简单的可重现的例子来重现这个问题,所以我想出了以下内容:
# test.py
from freezegun import freeze_time
from datetime import datetime
import stuff_in_between
import test_time # <-- note this unused import
with freeze_time(datetime(2019, 1, 1, 1, 1, 1, 1), ignore=['test_time']):
print(f'frozen time: {datetime.now()}')
stuff_in_between.call_test_time()
# stuff_in_between.py
def call_test_time():
import test_time
test_time.test_time()
# test_time.py
from datetime import datetime
def test_time():
print(f'real datetime.now: {datetime.now()}')
此代码正常工作, freeze_time 忽略test_time
并打印real datetime.now: <real time>
. 但是,如果我忽略了标记为未使用的导入test.py
,它就不起作用 - freeze_time 不是ignore
模块并且脚本会打印出来real datetime.now: <fake time>
。
我想我可以在我真正的 Django go 中尝试类似的东西,所以我做了以下操作:
...
import botocore
import botocore.auth
# hell, try to import everything possible related to S3
with freeze_time(datetime_in_past, ignore=['botocore']:
...
# create some instances, that also save files to S3
无论我导入或忽略什么,这都不起作用,botocore.auth
仍然继续使用FakeDatetime
......是否有错误freezegun
?还是我以某种方式滥用图书馆?为什么它会这样?
只是为了澄清-我不关心使用时间偏移设置的文件。它们可以在 S3 中实时设置。我只关心用冻结时间保存的模型。所以如果我有以下模型:
class Image(models.Model):
date_created = models.DateTimeField(auto_now_add=True)
file = models.ImageField(...)
字段date_created
将使用冻结时间。