Python 错误处理:如何正确区分异常的优先级
有两个功能:一个是下载excel文件(Python 错误处理:如何正确区分异常的优先级,python,django-rest-framework,Python,Django Rest Framework,有两个功能:一个是下载excel文件(ExcelFileUploadView(APIView)),另一个是处理下载的文件(def parse\u excel\u rfi\u sheet)。 函数parse\u excel\u rfi\u sheet在ExcelFileUploadView(APIView) 问题是,当解析excel\u rfi\u工作表中发生错误时,我看不到调用{“常规错误”:[“excel文件解析期间出错。未知模块单元”]} 相反,我总是看到电话 {"general_error
ExcelFileUploadView(APIView)
),另一个是处理下载的文件(def parse\u excel\u rfi\u sheet
)。
函数parse\u excel\u rfi\u sheet
在ExcelFileUploadView(APIView)
问题是,当解析excel\u rfi\u工作表中发生错误时,我看不到调用{“常规错误”:[“excel文件解析期间出错。未知模块单元”]}
相反,我总是看到电话
{"general_errors": ["Error during file upload"]}
这就是为什么我不能理解错误是在什么阶段发生的:下载文件的时候还是处理文件的时候。
如何更改此设置?因为您正在从ExcelFileUploadView
调用parse\u excel\u rfi\u sheet
,每当异常{“general\u errors”:[“excel文件解析期间出错。未知模块单元”]}从parse_excel\u rfi_sheet
函数try
中引发,从ExcelFileUploadView
中阻止失败,并进入除
之外,并引发异常{“常规错误”:[“文件上载期间出错”]
您可以通过打印由ExcelFileUploadView
函数引发的异常来验证这一点。
将try块更改为以下内容:
try:
file = default_storage.save(filename, f)
r = parse_excel_rfi_sheet(file)
status = 200
except Exception as e:
print("Exception raised ", e)
raise Exception({"general_errors": ["Error during file upload"]})
引发异常(…)
生成一个新的异常
实例并引发该实例。
这意味着,尝试。。。除了put
中的
,它有效地丢弃了捕获的异常,并将其替换为一个新的异常,并显示消息“文件上载时出错”,这就是为什么您总是看到相同的消息
处理此问题的一种干净方法是定义异常
(例如,无效格式异常
)的自定义子类,并在parse\u excel\u rfi\u sheet
中提出该子类,在put
中有两个不同的案例除外:
class InvalidFormatException(Exception):
pass
[...]
def parse_excel_rfi_sheet(file):
workbook = load_workbook(filename=file)
sheet = workbook["RFI"]
curent_module_coordinate = []
try:
....
curent_module_coordinate.append(sheet['E688'].value)
curent_module_coordinate.append(sheet['E950'].value)
if check_exel_rfi_template_structure(structure=curent_module_coordinate):
file_status = True
else:
file_status = False
except:
raise InvalidFormatException({"general_errors": ["Error during excel file parsing. Unknown module cell"]})
您的put
将变成:
def put(self, request, format=None):
if 'file' not in request.data:
raise ParseError("Empty content")
f = request.data['file']
filename = f.name
if filename.endswith('.xlsx'):
try:
file = default_storage.save(filename, f)
r = parse_excel_rfi_sheet(file)
status = 200
except InvalidFormatException:
raise # pass on the exception
except:
raise Exception({"general_errors": ["Error during file upload"]})
finally:
default_storage.delete(file)
else:
status = 406
r = {"general_errors": ["Please upload only xlsx files"]}
return Response(r, status=status)
警告:正如对本答案的评论中所指出的,请注意,尽管没有直接询问,但应进一步修改OP的代码,以删除裸露的,除了:
子句,如下所示 您的问题来自捕获绝对所有的异常,首先在解析excel\rfi\u表
中,然后再次在放置
方法中。裸except子句(except:whatever_code_here
)和大的try
块都是反模式-您只想捕获在给定点上期望的确切异常(使用except(SomeExceptionType,AnotherExceptionType,…)例如e:
,并且在try
块中拥有尽可能少的代码,这样您就有信心知道异常来自何处
此规则的唯一例外(没有双关语)是更高级别的“catch all”处理程序,用于捕获意外错误,记录这些错误(因此您可以跟踪发生的情况),并向用户显示一条友好的错误消息-但即使如此,您也不希望看到一个简单的except子句,而是希望看到一个Exception作为e
TL;DR:永远不要假设发生了什么异常,发生在哪里,为什么发生,永远不要默默地传递异常(至少要记录它们,并检查日志).关于使用bare except子句的异常处理的答案是一个非常糟糕的答案。正确的异常处理规则#1:永远不要使用bare except子句。@Brunodesshuilliers问题不是关于正确的异常处理,我不主张我的解决方案在“正确”方面是正确的异常处理,因为这与主题相去甚远。OP想知道为什么他的异常会被取消,我提供了一个例子来解释如何解决这个问题。深入研究OP代码中可能存在的错误是为了,而不是为了。@GPhilo但听起来它不像OP预期的那样工作,对CR无效。@Mast this questi当然,on不属于CR。我只是说,我正在详细说明OP的代码不好的原因(当然,除了请求的问题)会偏离主题。@GPhilo我想我们必须同意不同意。但还是要感谢您添加了警告。谢谢,我根据您添加的内容编写了一个审阅代码,现在我收到的是一个特定错误,而不是一般消息。
def put(self, request, format=None):
if 'file' not in request.data:
raise ParseError("Empty content")
f = request.data['file']
filename = f.name
if filename.endswith('.xlsx'):
try:
file = default_storage.save(filename, f)
r = parse_excel_rfi_sheet(file)
status = 200
except InvalidFormatException:
raise # pass on the exception
except:
raise Exception({"general_errors": ["Error during file upload"]})
finally:
default_storage.delete(file)
else:
status = 406
r = {"general_errors": ["Please upload only xlsx files"]}
return Response(r, status=status)