【问题标题】:Passing method call as a variable to error handling function将方法调用作为变量传递给错误处理函数
【发布时间】:2012-02-14 12:37:19
【问题描述】:

尝试在我的代码中不添加 buku 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 对象(汤)的方法调用传递给泛型 try/except 函数?

  • 尝试了 lambda,但理解不够,无法使其与参数和汤一起使用。
  • 看了Partial,但没看出来怎么叫美汤法
  • 看了this 但没看到汤怎么传?

我的代码:

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 函数到达之前一直触发。我该如何解决这个问题?

【问题讨论】:

  • 您可能已经知道这一点,但使用裸露的except 是危险的做法,因为它几乎可以捕获所有可能的问题。您应该提供您愿意转换为 if_error 值的异常。

标签: python beautifulsoup


【解决方案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)

【讨论】:

  • 解决方案有效。比构建参数 dict description = if_error(soup.find,'','div',attrs={'class':'listing_description_module description'}) 更具可读性
【解决方案2】:

您的问题是您将 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={}, '')

【讨论】:

  • arg 后面的非关键字 arg 代码为 description = findError(soup,'div', attrs={'class':'listing_description_module description'},'') / 更改为 description = findError(soup,'div', {'class':'listing_description_module description'},'') / 和 findError 函数为 return soup.find(arg1, attrs=arg2)
  • 传递函数不仅在 Python 中是可能的,而且是被鼓励的。查看 Meitham 的答案,了解解决此问题的好方法。
  • attrs={} 的意义何在?你有findError 接受souparg1arg2error,bot 不是attrs
  • Meitham 的解决方案肯定是您想要的
  • @thagorn 同意了。 Meitham 的解决方案以被问到的方式回答了这个问题,传递了“a”fn。但是,您的方法有助于以简单易懂的方式说明为 beautifulsoup 量身定制的解决方案。
【解决方案3】:

做这样的事情怎么样?

def if_error(f,f_args,fail_value):
    try:
      value = f(**f_args).text
    except:
      value = fail_value
    return value

其中f_args 是您要传递给函数f 的参数的字典。

【讨论】:

  • 甜蜜!我终于明白了。这确实有效地让一个函数在一个地方命名并在另一个地方执行它。良好的可重用性。 arg_dict = {'name':'div','attrs':{'class':'listing_description_module description'}} description = if_error(soup.find,arg_dict,'')
【解决方案4】:

您需要为您的错误屏蔽函数提供几项:要转换为默认值的异常、默认值、要调用的函数及其参数:

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'

如您所见,最后一次调用引发了异常,因为我们没有用它捕获ValueErrors。

【讨论】:

    猜你喜欢
    • 2021-02-28
    • 1970-01-01
    • 2016-10-23
    • 1970-01-01
    • 2018-09-03
    • 2014-09-27
    • 1970-01-01
    • 1970-01-01
    • 2014-03-20
    相关资源
    最近更新 更多