将方法调用作为变量传递给错误处理函数

3 投票
4 回答
576 浏览
提问于 2025-04-17 10:39

我想在代码中实现简单的错误处理,但又不想加太多的try / except语句。

我的if_error函数是想模仿Excel中的iferror(value,value_if_error)公式。

If the value (another formula) is valid, 
     return its resulting value 
else 
     return value_if_error

我该如何将一个beautifulsoup对象(soup)的方法调用和参数传递给一个通用的try/except函数呢?

  • 我试过用lambda,但对它的理解不够,没能让它和参数及soup一起工作。
  • 我看过Partial,但没明白它是怎么调用beautiful soup的方法的。
  • 我还看过这个,但没看到soup是怎么传递的。

我的代码:

def if_error(fn,fail_value):
    try:
      value = fn
    except:
      value = fail_value
    return value

def get_trulia_data(soup):
    d = dict()

    description = if_error(soup.find('div', attrs={'class': 'listing_description_module description'}).text,'')

    sale_price = if_error(soup.find('div', attrs={'class': 'price'}).text,'0')
    sale_price = re.sub('[^0-9]', '', sale_price)

    details = if_error(soup.find('ul', attrs={'class': 'listing_info clearfix'}),'')

    bed = if_error(soup.find('input', attrs={'id': 'property_detail_beds_org'})['value'],'')
    bath = if_error(soup.find('input', attrs={'id': 'property_detail_baths_org'})['value'],'')

    ...

    return d

错误:

Traceback (most recent call last):
data_dict = get_trulia_data(url)
description = if_error(soup.find('div', attrs={'class': 'listing_description_module description'}).text,'')
AttributeError: 'NoneType' object has no attribute 'text'

soup.find方法在到达if_error函数之前就一直在执行。我要怎么解决这个问题呢?

4 个回答

0

你需要给你的错误处理函数提供几个东西:你想要转换成默认值的异常类型、默认值、要调用的函数,以及这个函数的参数:

def if_error(exceptions, fail_value, fn, *args, **kwargs):
    try:
      return fn(*args, **kwargs)
    except exceptions:
        return fail_value

def test_fn(x):
    return int(x)

if __name__=='__main__':
    print if_error(ValueError, 0, test_fn, '42')
    print if_error(ValueError, -1, test_fn, 'abc')
    print if_error(TypeError, -2, test_fn, 'abc')

这样我们就得到了:

42
-1
Traceback (most recent call last):
  File "test.py", line 13, in <module>
    print if_error(TypeError, -2, test_fn, 'abc')
  File "test.py", line 3, in if_error
    return fn(*args, **kwargs)
  File "test.py", line 8, in test_fn
    return int(x)
ValueError: invalid literal for int() with base 10: 'abc'

正如你所看到的,最后一次调用让异常抛出来了,因为我们没有用它来捕捉 ValueError

0

你的问题是,你把 soup.find() 的结果传给了 if_error,而不是把函数本身传过去。你可以试着把实际的函数传给 if_error,但我建议你这样做:

def findError(soup, arg1, arg2, error):
    try:
        return soup.find(arg1, arg2)
    except:
        return error

然后调用:

findError(soup, 'div', attrs={}, '')
1

这样怎么样:

def if_error(fn, fail_value, *args, **kwargs):
    try:
      return fn(*args, **kwargs)
    except:
        return fail_value

def test_fail(x):
    raise ValueError(x)

def test_pass(x):
    return x

if __name__=='__main__':
    print if_error(test_fail, 0, 4)
    print if_error(test_pass, 0, 5)

撰写回答