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

为何pytest patch无法Mock动态获取的Pandas read_csv函数?

问题:Mock动态字典中的Pandas read_csv函数失效

业务代码示例:

import pandas as pd

format_read_func_mapping = {"csv": pd.read_csv, "parquet": pd.read_parquet}

def my_func(s3_path, file_format):
    read_func = format_read_func_mapping[file_format]
    df = read_func(f"{s3_path}")
    return df

测试代码:

from unittest.mock import patch

@patch(f"{MODULE_PATH}.pd.read_csv")
def test_my_func(self, mock_read_csv):
    mock_read_csv.side_effect = [my_test_data_frame]
    my_func(dummy_s3_path, "csv")

现象:期望测试使用Mock返回测试数据,但实际调用了真实的pandas.read_csv;若在my_func中直接调用pd.read_csv而非通过字典获取,Mock能正常工作。


原因分析

这不是pytest的限制,是Mock方式没匹配代码的执行逻辑:

  • 模块加载时,format_read_func_mapping字典就已经存储了真实的pd.read_csv函数引用
  • 你用patch(f"{MODULE_PATH}.pd.read_csv")修改的是模块命名空间里的pd.read_csv,但字典里保存的还是最初的真实函数引用,所以my_func调用的是字典里的真实函数,而非Mock版本

解决方法

方法1:延迟获取函数引用

修改字典存储函数名称,每次调用时通过getattr从pd中动态获取,确保每次都能拿到最新的(包括被Mock的)函数引用:

import pandas as pd

format_read_func_mapping = {"csv": "read_csv", "parquet": "read_parquet"}

def my_func(s3_path, file_format):
    read_func = getattr(pd, format_read_func_mapping[file_format])
    df = read_func(f"{s3_path}")
    return df

方法2:直接Mock字典中的函数引用

跳过模块里的pd.read_csv,直接patch字典中存储的那个函数引用:

from unittest.mock import patch

@patch(f"{MODULE_PATH}.format_read_func_mapping['csv']")
def test_my_func(self, mock_read_csv):
    mock_read_csv.return_value = my_test_data_frame
    my_func(dummy_s3_path, "csv")

方法3:动态生成函数映射

把字典改成每次调用时动态生成的逻辑,确保每次都从pd中取最新函数:

import pandas as pd

def get_read_func(file_format):
    func_map = {"csv": pd.read_csv, "parquet": pd.read_parquet}
    return func_map[file_format]

def my_func(s3_path, file_format):
    read_func = get_read_func(file_format)
    df = read_func(f"{s3_path}")
    return df

内容的提问来源于stack exchange,提问作者Sapience

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 14:43:17