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

如何用pytest对pandas read_csv做Monkey Patch?补丁失效排查

问题分析与解决方案

一、Monkey Patch未生效的原因

你当前是对全局的pd.read_csv打补丁,但circle.py模块在导入pandas后,会持有自己的pd引用。测试时修改全局的pd不会影响circle模块内部已导入的pd对象,所以补丁没生效。

修复方法:
把补丁的目标改成circle模块内的pd.read_csv,也就是把测试代码里的:

monkeypatch.setattr(pd, "read_csv", mock_read_csv)

改成:

monkeypatch.setattr(circle.pd, "read_csv", mock_read_csv)

二、read_rads函数的逻辑错误

除了补丁问题,你的read_rads函数里用df.iterrows()的方式也错了:df.iterrows()返回的是(行索引, 行数据)的元组,你现在取x[0]拿到的是行索引(0、1、2...),不是CSV里的半径值。

修复方法:
修改read_rads里的列表推导,取行数据中的数值,比如用更简洁高效的方式:

return df.iloc[:, 0].apply(get_area).tolist()

三、测试数据注入方式的正确性

你用Monkey Patch替换read_csv返回固定DataFrame的方式是完全正确的,这是测试IO依赖代码的标准做法,能避免真实读取文件带来的不确定性。

修改后的完整代码

circle.py(修正read_rads)

import math
import pandas as pd

def get_area(r):
    if not type(r) in [int, float]:
        raise TypeError("Non numeric value") 
    return math.pi*(r**2)

def read_rads():
    df = pd.read_csv('radii.csv', header=None, index_col=None)
    # 修正取值逻辑
    return df.iloc[:, 0].apply(get_area).tolist()

if __name__ == '__main__':
    print(get_area(2))
    print(read_rads())

test_circle.py(修正补丁目标)

import pytest
import circle
import math
import pandas as pd

def test_get_area():
    assert circle.get_area(1) == math.pi * 1**2
    assert circle.get_area(3) == math.pi * 3**2

def test_if_get_area_for_string_input():
    with pytest.raises(TypeError):
        circle.get_area('some string')

def test_read_radii(monkeypatch):
    def mock_read_csv(*args, **kwargs):
        return pd.DataFrame([0,1,2,3,5])

    # 修正补丁目标为circle模块内的pd.read_csv
    monkeypatch.setattr(circle.pd, "read_csv", mock_read_csv)
    res = circle.read_rads()
    assert res == [0.0, 3.141592653589793, 12.566370614359172, 28.274333882308138, 78.53981633974483]

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 00:25:16