【问题标题】:Twice-ran behavior of a try-catch-raise exception clause in PythonPython 中 try-catch-raise 异常子句的两次运行行为
【发布时间】:2016-10-27 20:17:13
【问题描述】:

在下面的最小示例中,我用我自己的方法 safe_apply 包装了 pandas.DataFrame.apply 方法。此方法与普通的apply 有两个不同之处:

  1. 不是在NDFrame 中返回值,而是将它们附加到列表results
  2. 如果捕获到异常,则在引发错误并终止执行之前打印results

代码如下:

from pandas.core.frame import DataFrame, Series
import pandas as pd

def safe_apply(df, func, **kwargs):
    results = []

    def new_func(srs):
        try:
            results.append(func(srs))
        except Exception as e:
            print(results)
            raise

    df.apply(new_func, **kwargs)
    return results

DataFrame.safe_apply = safe_apply

def f(srs):
    if (pd.notnull(srs['lat'])) & (pd.notnull(srs['long'])):
        return srs['lat'] + srs['long']
    else:
        raise ValueError


ex = pd.DataFrame({'lat': [1, 2, None], 'long': [1, 2, None]}, index=['A', 'B', 'C'])
ex.safe_apply(f, axis='columns')

当我执行此操作时,除了将函数 f 应用于 ex 的前两行然后在第三行失败的结果之外:print 来自 [2.0, 4.0],然后是 @987654332 @

相反,我得到了 ValueError 行输出:

[2.0, 4.0]
[2.0, 4.0, 2.0, 4.0]
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-1-382c07ef0919> in <module>()
     26         raise ValueError
     27 
---> 28 ex.safe_apply(f, axis='columns')

<ipython-input-1-382c07ef0919> in safe_apply(df, func, **kwargs)
     12             raise
     13 
---> 14     df.apply(new_func, **kwargs)
     15 
     16     return results

C:\Users\Alex\Anaconda3\lib\site-packages\pandas\core\frame.py in apply(self, func, axis, broadcast, raw, reduce, args, **kwds)
   4059                     if reduce is None:
   4060                         reduce = True
-> 4061                     return self._apply_standard(f, axis, reduce=reduce)
   4062             else:
   4063                 return self._apply_broadcast(f, axis)

C:\Users\Alex\Anaconda3\lib\site-packages\pandas\core\frame.py in _apply_standard(self, func, axis, ignore_failures, reduce)
   4155             try:
   4156                 for i, v in enumerate(series_gen):
-> 4157                     results[i] = func(v)
   4158                     keys.append(v.name)
   4159             except Exception as e:

<ipython-input-1-382c07ef0919> in new_func(srs)
      7     def new_func(srs):
      8         try:
----> 9             results.append(func(srs))
     10         except Exception as e:
     11             print(results)

<ipython-input-1-382c07ef0919> in f(srs)
     24         return srs['lat'] + srs['long']
     25     else:
---> 26         raise ValueError
     27 
     28 ex.safe_apply(f, axis='columns')

ValueError: occurred at index C

意味着代码到达异常子句,打印出results,然后以某种方式再次运行函数(?),而不是抛出错误并停止。

为什么会这样?

【问题讨论】:

    标签: python pandas exception exception-handling


    【解决方案1】:

    具体见docstring上的注释部分

    在当前实现中,apply 在第一列/行上调用 func 两次,以决定它是否可以采用快速或慢速代码路径。如果 func 有副作用,这可能会导致意外行为,因为它们会对第一列/行生效两次。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-04-15
      • 2013-06-27
      • 2023-03-25
      • 2013-05-26
      • 2017-10-16
      • 1970-01-01
      • 2014-09-09
      • 1970-01-01
      相关资源
      最近更新 更多