Expectation handling in python.

huangapple go评论97阅读模式
英文:

Expectation handling in python

问题

以下是两个函数定义:

def function1():
   try:
      # 代码
      # 代码

      # 此处是读取文件的代码

      # 代码
      return smth
   
   except Exception as e:
      raise Exception('smth1smth1') from e
   

def function2():
   try:
      # 代码
      smth = function1()
      data = {# 一些 JSON 键值对}
      data2 = request.post(smth123, data)
      # 代码
      return smth
   
   except Exception as e:
      print('error:%s, error:%s' % (data.key1, data.key2, str(e)))
      raise Exception('smth2smth2') from e

对于这个测试案例,文件在这里是缺失的。我期望会得到文件丢失的异常,但由于变量"data"未被赋值,我也会得到在赋值之前引用变量的错误。我不想看到从第二个函数即function2抛出的异常(错误),而是只想看到从第一个函数即function1抛出的异常,如果有的话。如何实现这一点?

英文:

Below are two function definition

def function1():
   try:
      #Code
      #Code

      #code to read file is here

      #code
      return smth
   
   except Exception as e:
      raise Exception ('smth1smth1') from e
   

def function2():
   try:
      #Code
      smth=function1()
      data= {#some json key value pairs}
      data2=request.post(smth123,data)
      #code
      return smth
   
   except Exception as e:
      print('error:%s, error:%s , %(data.key1, data.key2, str(e)))
      raise Exception ('smth2smth2') from e   

The test case for this is the file is missing here. I am getting the file missing exception as expected but as variable "data" is not assigned I am also getting the variable referenced before assignment error as well.
I don't want to see the exception (error) thrown from the second function i.e function 2 and see the exception from the first i.e. function1 if there is any. How can I achieve this

答案1

得分: 1

在你的except块中的代码不应该依赖于可能在try块中失败的任何内容。所以,你可以在except中不使用data

def function2():
   try:
      #代码
      smth = function1()
      data = {#一些JSON键值对}
      data2 = request.post(smth123, data)
      #代码
      return smth
   except Exception as e:
      print('错误:', e)
      raise Exception('smth2smth2') from e

或者你可以使用多个try块:

def function2():
   try:
      #代码
      smth = function1()
   except Exception as e:
      print('错误:%s,错误:%s' % (data.key1, data.key2, str(e)))
      raise Exception('smth2smth2') from e
   try:
      data = {#一些JSON键值对}
      data2 = request.post(smth123, data)
      #代码
      return smth
   except Exception as e:
      print('错误:%s,错误:%s' % (data.key1, data.key2, str(e)))
      raise Exception('smth2smth2') from e

或者你可以使用不同的Exception类,在单个try中有多个except块,每个匹配特定类别的异常(假设每个异常可能在try的不同部分引发):

class Function1Exception(Exception):
    pass

def function1():
    try:
        #代码
        return 'smth'
    except Exception as e:
        raise Function1Exception('smth1smth1') from e

def function2():
    try:
        #代码
        smth = function1()
        data = {'key': 'value'}
        data2 = request.post(smth, data)
        #代码
        return smth
    except Function1Exception as e:
        print('function1失败:', e)
    except RequestException as e:
        print(f'request失败: {data.key1}, {data.key2}, 错误: {e}')
        raise Exception('smth2smth2') from e

请注意,如果你在function1中根本不进行异常封装,那么你将自动获得一个更有用的异常类,如FileNotFoundError,就像request.post在失败时会引发RequestException一样,而不是任何旧的Exception。重新引发通用的异常(即普通的Exception)实际上会丢失信息,使错误处理变得更加困难。

英文:

The code in your except block needs to not have dependencies on anything that might have failed in the try block. So you either need to not have data in the except:

def function2():
   try:
      #Code
      smth=function1()
      data= {#some json key value pairs}
      data2=request.post(smth123,data)
      #code
      return smth
   except Exception as e:
      print('error:', e)
      raise Exception('smth2smth2') from e

or you need multiple try blocks:

def function2():
   try:
      #Code
      smth=function1()
   except Exception as e:
      print('error:%s, error:%s , %(data.key1, data.key2, str(e)))
      raise Exception('smth2smth2') from e
   try:
      data= {#some json key value pairs}
      data2=request.post(smth123,data)
      #code
      return smth
   except Exception as e:
      print('error:%s, error:%s , %(data.key1, data.key2, str(e)))
      raise Exception('smth2smth2') from e   

Or you can use different Exception classes to have multiple except blocks in a single try, each matching a specific class of exception (with the assumption being that each might get raised in a different part of the try):

class Function1Exception(Exception):
    pass

def function1():
    try:
        #code
        return 'smth'
    except Exception as e:
        raise Function1Exception('smth1smth1') from e
   

def function2():
    try:
        #Code
        smth = function1()
        data = {'key': 'value'}
        data2 = request.post(smth, data)
        # code
        return smth
    except Function1Exception as e:
        print('function1 failed:', e)
    except RequestException as e:
        print(f'request failed: {data.key1}, {data.key2}, error: {e}')
        raise Exception('smth2smth2') from e   

Note that if you weren't doing that except-wrapping in function1 at all, you would automatically get a more useful exception class like FileNotFoundError, the same way request.post will raise a RequestException on a failure rather than any old Exception. Re-raising a more generic exception (i.e. a regular Exception) is actually losing information and making it harder to handle the error.

huangapple
  • 本文由 发表于 2023年8月4日 23:53:59
  • 转载请务必保留本文链接:https://go.coder-hub.com/76837485.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定