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 对您提出的异常没有任何处理。我正在考虑您需要引发异常,否则3
和6
之间没有区别。第二个建议是更改您的函数 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中函数嵌套循环语句时,return 如何正确使用返回值