TypeError: strip_name() got an unexpected keyword argument ‘many‘问题的解决

引言

在读一本书《Learn Python Programming》1的第8章,按照书中的讲解先后安装了marshmallowpytest第三方库,j进而按照书中的代码结构和代码在ch08文件夹下运行pytest tests,出现如下错误:
错误结果截图
ch08中的api.py的代码为:

# ch08/api.py
'''
This program needs: pip install marshmallow; pip install pytest
'''
import os 
import csv
from copy import deepcopy

from marshmallow import Schema, fields, pre_load 
from marshmallow.validate import Length, Range 

class UserSchema(Schema):
    ''' Represent a *valid* user. '''
    email = fields.Email(required=True)
    name = fields.String(required=True, validate=Length(min=1))
    age = fields.Integer(required=True, validate=Range(min=18, max=65))
    role = fields.String()
    
    @pre_load(pass_many=False)
    def strip_name(self, data):
        data_copy = deepcopy(data)
        
        try:
            data_copy['name'] = data_copy['name'].strip()
        except (AttributeError, KeyError, TypeError):
            pass 
        return data_copy

schema = UserSchema()

def export(filename, users, overwrite=True):
    '''Export a CSV file.
    
    Create a CSV file and fill with valid users. if "overwrite"
    is False and file already exists, raise IOError.
    '''
    if not overwrite and os.path.isfile(filename):
        raise IOError(f"'{filename}' already exists")
    valid_users = get_valid_users(users)
    write_csv(filename, valid_users)
    
def get_valid_users(users):
    '''Yield one valid user at a time from users.'''
    yield from filter(is_valid, users)
def is_valid(user):
    '''Return whether or not the user is valid.'''
    return not schema.validate(user)

def write_csv(filename, users):
    '''Write a CSV given a filename and a list of users.
    
    The users are assumed to be valide for the given CSV structure.
    '''
    fieldnames = ['email', 'name', 'age', 'role']
    
    with open(filename, 'x', newline='') as csvfile:
        writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
        writer.writeheader()
        for user in users:
            writer.writerow(user)

ch08/tests/test_api.py中代码为:

# tests/test_api.py
import os 
from unittest.mock import patch, mock_open, call
import pytest
from ..api import is_valid, export, write_csv 

@pytest.fixture
def min_user():
    """ Represent a valid user with minimal data. """
    return {
        'email': 'minimal@example.com',
        'name': 'Primus Minimus',
        'age': 18,
    }

@pytest.fixture
def full_user():
    """Represent valid user with full data."""
    return {
        'email': 'full@example.com',
        'name': 'Minimus Primus',
        'age': 65,
        'role': 'emperor',
    }

@pytest.fixture
def users(min_user, full_user):
    """List of users, two valid and one invalid. """
    bad_user = {
        'email': 'invalid@example.com',
        'name': 'Horribilis',
    }
    return [min_user, bad_user, full_user]

class TestIsValid:
    """Test how code verifies whether a user is valid or not. """
    def test_minimal(self, min_user):
        assert is_valid(min_user)

从上面错误截图并结合代码可以分析出,该错误与我们所给出的测试数据无关,并且指向了api.py文件中的strip_name()方法。

问题解决

从事后来看,我昨晚一遇到该问题,比较慌乱和焦虑。混乱想,认为我电脑上安装的Python版本老,或者说准备在另一台台式机上重新试试代码。今早到办公室解决该问题后,冷静下来,很容易能分析出该问题的症结所在:因为方法strip_name()被装饰器@pre_load(pass_many=False)所装饰,那么问题的症结只能是第三方库marshmallow。这是马后炮,当时遇到问题时可没这么想。

看了下自己电脑上安装的的marshmallow为:marshmallow 3.19.0。又在网络上搜索了该问题,看到如下:
搜索得到的关键信息
于是将api.py代码中的strip_name()方法签名改为:

@pre_load(pass_many=False)
def strip_name(self, data, **kwargs):

仅仅增加了参数**kwargs,其他代码保持不变。运行成功,如下图所示:
运行成功结果截图

结束语

在读相对比较老的书籍时,书中的代码可能是针对老版本库的代码。而自己电脑上安装的一般是比较新的第三方包。这时,可能会出现代码错误。解决该错误的过程能提高自己的debug能力。比较蹊跷的是,上面test_api.py是单元测试代码,也就是说是测试api.py的代码,而我现在是在找出和解决test_api.py代码出现的问题,所有应该被称为元测试。如果我们把相关问题解决了,实际上是将书中的老代码更新到了新版本。

遇到问题不要慌,要淡定。冷静的分析错误根源。

Python语言很好入门,但是,应用好Python将是一个非常广阔的话题,所耗费的时间将是很多的。如果从事Python相关职业,可能长期在用。在此引用书《Learning Python》2中话与大家共勉:

Applying Python is actually a larger topic than learning Python.


  1. Fabrizio Romano. Learn Python Programming. 2ed. Packt, 2018. ↩︎

  2. Mark Lutz. Learning Python. 5ed. O’Reilly, 2013. ↩︎

  • 8
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值