Python:循环数据时继续通过“RuntimeError”

Posted

技术标签:

【中文标题】Python:循环数据时继续通过“RuntimeError”【英文标题】:Python: Continue past a "RuntimeError" when looping through data 【发布时间】:2021-07-28 23:29:02 【问题描述】:

在循环数据列表时,我将如何继续通过 RuntimeError? 例如,假设我的函数 f 如下:

t_ints = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
 
def f(x):
    for i in x:
        if i==3:
            continue
        
        elif i ==6:
            raise RuntimeError('NOP')
        print(f'Processing integer i')
    
    print("Done")
    return

f(t_ints)

该函数将打印除 3 之外的每个数字,传递 3 并继续到 4。但是当它达到 6 时,它将产生一个名为 NOP 的 RunTimeError。所以输出是:

Processing integer 1
Processing integer 2
Processing integer 4
Processing integer 5
---------------------------------------------------------------------------
RuntimeError                              Traceback (most recent call last)
c:\Users\jalmendarez.MSQT\Visual Studio Code\Test Notebooks\Test Sheet 1.py in 
     251     return
     252 
---> 253 f(t_ints)

c:\Users\jalmendarez.MSQT\Visual Studio Code\Test Notebooks\Test Sheet 1.py in f(x)
      245 
      246         elif i ==6:
----> 247             raise RuntimeError('NOP')
     248         print(f'Processing integer i')
     249 

RuntimeError: NOP

我想传递整数列表,如上面的 t_ints,并将 for 循环中的函数应用于每个列表。

z=[
    [11, 22, 33, 3, 55, 66, 87, 8, 9, 10],
    [31, 3, 53, 54, 3, 66, 7, 8, 9, 10],
    [2,4,6,8,10,11,35]
]

所以我编写了下面的代码来循环遍历每个列表,它忽略并传递 3 并继续列表。但是,当它遇到 6 时,由于错误而停止并且不会继续。我尝试使用 try/except。我希望我的循环忽略 RuntimeError('NOP') 并继续。

INPUT:
for i in z:
    try:
        f(i)
    except RuntimeError:
        pass
OUTPUT:
Processing integer 11
Processing integer 22
Processing integer 33
Processing integer 55
Processing integer 66
Processing integer 87
Processing integer 8
Processing integer 9
Processing integer 10
Done
Processing integer 31
Processing integer 53
Processing integer 54
Processing integer 66
Processing integer 7
Processing integer 8
Processing integer 9
Processing integer 10
Done
Processing integer 2
Processing integer 4

我想要的实际输出是:

Processing integer 11
Processing integer 22
Processing integer 33
Processing integer 55
Processing integer 66
Processing integer 87
Processing integer 8
Processing integer 9
Processing integer 10
Done
Processing integer 31
Processing integer 53
Processing integer 54
Processing integer 66
Processing integer 7
Processing integer 8
Processing integer 9
Processing integer 10
Done
Processing integer 2
Processing integer 4
Processing integer 8
Processing integer 10
Processing integer 11
Processing integer 35

关于如何使用类似于“继续”的内容来解决引发的错误的任何想法?

——编辑—— 读这个!!

好的,这是真正的问题,因为它确实与我上面创建的函数无关。抱歉读了这么久,但这是必要的。

我创建了函数 f 作为示例,看看我是否可以通过 RunTimeError。这是为了解决我遇到的更大问题的尝试。我有大约一百万行和 23 列的 df。有一个 ID 列。但实际上只有大约 18,000 个唯一 ID。所以我创建了一个遍历每个唯一 ID 的 for 循环。在该循环中,我为每个 ID 创建了一个带有行/列的过滤数据框。使用过滤后的数据,我正在运行基于列中可用值的曲线拟合,以及我创建的一些函数来计算指数下降曲线。这是一个简单的等式。 http://www.petrocenter.com/reservoir/DCA_theory.htm

运行曲线拟合后,我将曲线拟合求解的参数插入我的指数下降曲线函数。我将该函数的新值作为新列添加到 for 循环内该唯一 ID 的数据框。然后,我将每个唯一 ID 数据框与字典中的新曲线拟合函数数据列一起存储。因此,我可以访问具有原始值的每个 IDs 数据框,以及基于使用指数下降曲线拟合的曲线的估计值。

基本上我要拟合 18,000 次曲线。通过该过程,某些曲线拟合会产生无法求解曲线拟合的 RunTimeError。我同意并非所有问题都得到解决。我没有时间检查 18,000 个唯一 ID 数据以确保它足够干净以适合曲线。因此,我希望能够跳过出现 RunTimeError 的那些 ID 实例,然后转到 for 循环中的下一个唯一 ID。

【问题讨论】:

你想达到什么目的?这是可能的,但我没有看到好处? 为什么不直接删除 raise 运行时错误并放入自定义错误消息。 raise 条件似乎打破了循环,并且错误消息无论如何都没有贡献 如果你在 for 循环中引发,它会破坏它。除非您在第一个函数中尝试/除外,否则无法解决。 问题是函数f。它引发异常并立即停止循环。没有一些英雄事迹,你就无法解开这个钟声。你有能力改变f 所做的事情吗?如果您对 6 的测试只是引发错误的调用的替代,您可以在 f 中捕获它。 我创建了函数 f 作为示例,看看我是否可以通过 RunTimeError。这是为了解决我遇到的更大问题的尝试。我有大约一百万行的df。有一列包含大量数据的 ID。但实际上只有大约 18,000 个唯一 ID。所以我创建了一个循环遍历每个唯一 ID 的 for 循环。在该循环中,我为每个 ID 创建了一个带有行/列的过滤数据框。使用过滤后的数据,我正在根据列中可用的值和我预先确定的一些函数运行曲线拟合.....继续...... 【参考方案1】:

实施问题是您的错误处理程序必须处于您希望处理错误的级别。您的代码无法处理处理循环中的错误。当您引发错误时,您的函数退出循环,退出函数,并引发错误以供调用程序处理。继续循环为时已晚。

如果你想在函数内继续循环,那么你必须在函数内处理异常。很简单,您根本不应该提出异常。正如您所描述的所需功能,case 3 和 case 6 之间没有区别。

def f(x):
    for i in x:
        if i == 3 or i == 6:
            continue
        
        print(f'Processing integer i')
    
    print("Done")
    return

回应 OP 的编辑

我认为您已经确定了帖子的核心问题:在您发布的代码中,循环本身引发了异常;在您的实际示例中,循环 calls 一个函数,该函数引发异常。看起来你需要的代码很简单,像这样:

for row in df:
    try:
        params = fit_function(row)
    exception RuntimeError:
        print(row, " failed to fit.)
        continue   # if there is more row processing for a successful fit.

【讨论】:

感谢您的反馈。请查看我更新的问题陈述以进一步了解我的问题。谢谢!【参考方案2】:

问题是您正在捕获并仅在外部循环中处理异常。您的函数 f 对您提出的异常没有任何处理。我正在考虑您需要引发异常,否则36 之间没有区别。第二个建议是更改您的函数 f,使其更具原子性,而不是在整个列表中运行,您可以使用一个函数来测试每个元素,并在某些情况下引发异常。

不要在循环中通过z 设置try-except 块,而是在f 函数中使用try-catch。您的代码将是这样的:

def f(x):
    for i in x:
        try:
            if i==3:
                continue        
            elif i ==6:
                raise RuntimeError('NOP')
            print(f'Processing integer i')
        except RuntimeError:
            continue
    
    print("Done")
    return
z=[
    [11, 22, 33, 3, 55, 66, 87, 8, 9, 10],
    [31, 3, 53, 54, 3, 66, 7, 8, 9, 10],
    [2,4,6,8,10,11,35]
]
for i in z:
    try:
        f(i)
    except RuntimeError:
        pass

-------版本后提供的详细信息的代码更新-

import pandas as pd
import logging

#Setup logging to a file
logging.basicConfig(filename='example.log', encoding='utf-8', level=logging.DEBUG)

#Your fit function
def fit(filtered_df):
     #Your exponential decline fit goes here
     return fit_results

#Reading your dataset
df = pd.read_csv("all_your_data.csv")

#list of dataframes results
fit_results = []
#list of failed_ids
failed_ids = []
for unique_id in df.YOUR_ID_COLUMN.unique():
    try:
        fit_results.append(fit(df[df.YOUR_ID_COLUMN==unique_id]))
    except RuntimeError:
        failed_ids.append(unique_id)
        logging.error(" curve fit failed".format(unique_id)) 

【讨论】:

感谢您的反馈。请查看我更新的问题陈述以进一步了解我的问题。谢谢! 了解 Jay,在这种情况下,只需遵循我上面提到的概念即可。创建一个函数以适应唯一 ID(您提到的 18000 之一)并将 try-except 子句放在对 fit 函数的调用之外。我建议在异常部分添加某种包含失败曲线 id 的日志记录。通过这种方式,您可以稍后检查单个故障,如果您的数据集足够好,它将远少于 18k 条曲线。希望对你有帮助 写的真好,能提供一个简单的代码例子吗? @JayAlmendarez,请查看代码示例的更新

以上是关于Python:循环数据时继续通过“RuntimeError”的主要内容,如果未能解决你的问题,请参考以下文章

Python:发生外部异常时如何正确继续while循环

python中函数嵌套循环语句时,return 如何正确使用返回值

在用KEIL调试程序时,遇到读取外部数据、死循环使得程序不能继续执行时怎么办?

Python怎么return后让循环继续运行?

Python怎么return后让循环继续运行?

如何在网络抓取时继续循环