Python 为什么覆盖函数a中的datetime.datetime会影响函数b的执行?

Python 为什么覆盖函数a中的datetime.datetime会影响函数b的执行?,python,unit-testing,scope,patch,Python,Unit Testing,Scope,Patch,我目前正在写一篇关于用Python进行单元测试的补丁的文章,我不明白为什么下面的方法有效。当我在该目录中执行pytest时,测试成功,尽管我的系统时间不是在1990年 我认为datetime.datetime=NewDate只会在test\u example.py中起作用。我想我需要更好地理解Python在哪里存储导入模块的名称/指针。有人能解释一下吗 示例.py #核心库模块 导入日期时间 def generate_filename(): 返回f“{datetime.datetime.now(

我目前正在写一篇关于用Python进行单元测试的补丁的文章,我不明白为什么下面的方法有效。当我在该目录中执行
pytest
时,测试成功,尽管我的系统时间不是在1990年

我认为
datetime.datetime=NewDate
只会在
test\u example.py
中起作用。我想我需要更好地理解Python在哪里存储导入模块的名称/指针。有人能解释一下吗

示例.py
#核心库模块
导入日期时间
def generate_filename():
返回f“{datetime.datetime.now():%Y-%m-%d}.png”
test_example.py
#核心库模块
导入日期时间
从unittest导入模拟
#第一方模块
从模拟示例导入生成文件名
类NewDate(datetime.datetime):
@类方法
def now(cls):
返回cls(1990,4,28)
def test_generate_filename():
datetime.datetime=NewDate
断言生成_filename()=“1990-04-28.png”

在您从模拟导入
的行上,示例导入生成\u文件名
,执行
导入日期时间
,因此
datetime.datetime
的值在导入后被覆盖
datetime.datetime=NewDate
。在同一程序上对任何全局变量(包括导入)进行的所有修改都会影响程序中的任何地方,无论它们位于不同的文件中


您实际上是在两个文件上访问相同的“变量”。如果您像从datetime导入datetime那样导入它(有关这方面的更多信息,请访问@Vishal Singh)

只要您修补了
datetime。datetime
模块中的
测试\u生成\u文件名
有两种导入需要注意

  • 导入a
    导入a.b
    (并像
    a.method
    a.b.method
    一样使用它)
  • 从导入b
    (如果在调用
    test\u generate\u filename
    之前导入b,则会保留未打补丁的引用,如果在该模块中使用,则会提供未打补丁的内容)
  • 在您的情况下,您像导入日期时间一样导入它,因此没有旧的引用,并且您已经对模块进行了修补,以便将来在任何文件中使用
    datetime.datetime.now()
    都会返回修补的内容,即90年代的日期


    如果在
    示例.py
    文件中尝试从datetime import datetime导入datetime之类的
    ,则断言将失败。

    这就是为什么在测试中不只是用假对象替换对象,而是使用
    mock.patch
    或类似工具,在离开范围后立即恢复修补。