Programing

파이썬에서 중첩 된 try / except 블록이 좋은 프로그래밍 습관입니까?

lottogame 2020. 6. 1. 07:41
반응형

파이썬에서 중첩 된 try / except 블록이 좋은 프로그래밍 습관입니까?


속성 호출로 사전에 액세스 해야하는 자체 컨테이너를 작성하고 있습니다. 컨테이너의 일반적인 사용법은 다음과 같습니다.

dict_container = DictContainer()
dict_container['foo'] = bar
...
print dict_container.foo

이런 식으로 쓰는 것은 어리석은 일이지만 그것이 제공해야 할 기능입니다. 나는 이것을 다음과 같은 방식으로 구현하려고 생각했다.

def __getattribute__(self, item):
    try:
        return object.__getattribute__(item)
    except AttributeError:
        try:
            return self.dict[item]
        except KeyError:
            print "The object doesn't have such attribute"

난인지 확실하지 중첩 된 시도 / 블록은 다른 방법을 사용하는 것입니다, 그래서 좋은 연습입니다 제외 hasattr()하고 has_key():

def __getattribute__(self, item):
        if hasattr(self, item):
            return object.__getattribute__(item)
        else:
            if self.dict.has_key(item):
                return self.dict[item]
            else:
                raise AttributeError("some customised error")

또는 다음 중 하나를 사용하고 다음과 같이 시도 블록을 시도하십시오.

def __getattribute__(self, item):
    if hasattr(self, item):
        return object.__getattribute__(item)
    else:
        try:
            return self.dict[item]
        except KeyError:
            raise AttributeError("some customised error")

가장 파이썬적이고 우아한 옵션은 무엇입니까?


첫 번째 예는 완벽합니다. 공식 파이썬 문서조차도 EAFP로 알려진이 스타일을 권장합니다 .

개인적으로 필요하지 않은 경우 중첩을 피하는 것이 좋습니다.

def __getattribute__(self, item):
    try:
        return object.__getattribute__(item)
    except AttributeError:
        pass  # fallback to dict
    try:
        return self.dict[item]
    except KeyError:
        raise AttributeError("The object doesn't have such attribute") from None

추신. has_key()파이썬 2에서는 오랫동안 사용되지 않습니다 item in self.dict. 대신 사용하십시오 .


Java에서는 실제로 흐름 제어에 예외를 사용하는 것은 좋지 않은 관행이지만 (주로 예외로 인해 jvm이 자원을 수집하도록 강요하기 때문에 ) 여기에는 더 중요한 두 가지 원칙이 있습니다 .Dy TypingEAFP . 이것은 기본적으로 객체가 작동한다고 생각하는 방식으로 객체를 사용하고 상황이 그렇지 않은 경우 처리하는 것이 좋습니다.

요약하면 유일한 문제는 코드가 너무 많이 들여 쓰기되는 것입니다. 느낌이 좋으면 lqc 제안과 같은 일부 중첩을 단순화하십시오.


구체적인 예를 들어 실제로 중첩 할 필요는 없습니다. try블록 의 표현식이 성공하면 함수가 반환되므로 전체 시도 / 제외 블록 이후의 모든 코드는 첫 번째 시도가 실패한 경우에만 실행됩니다. 그래서 당신은 할 수 있습니다 :

def __getattribute__(self, item):
    try:
        return object.__getattribute__(item)
    except AttributeError:
        pass
    # execution only reaches here when try block raised AttributeError
    try:
        return self.dict[item]
    except KeyError:
        print "The object doesn't have such attribute"

그것들을 중첩시키는 것은 나쁘지 않지만 평평하게두면 구조가 더 명확 해집니다. 순차적으로 일련의 일을 시도하고 작동하는 첫 번째 것을 반환합니다.

덧붙여서, 당신 __getattribute____getattr__여기서 대신에 정말로 사용하고 싶은지 생각하고 싶을 수도 있습니다. __getattr__일반 속성 조회 프로세스가 이미 실패했음을 알기 때문에 사용 하면 작업이 단순화됩니다.


In my opinion this would be the most Pythonic way to handle it, although and because it makes your question moot. Note that this defines__getattr__()instead of__getattribute__() because doing so means it only has to deal with the "special" attributes being keep in the internal dictionary.

def __getattr__(self, name):
    """only called when an attribute lookup in the usual places has failed"""
    try:
        return self.my_dict[name]
    except KeyError:
        raise AttributeError("some customized error message")

In Python it is easier to ask for forgiveness than permission. Don't sweat the nested exception handling.

(Besides, has* almost always uses exceptions under the cover anyways.)


Just be careful - in this case first finally is touched BUT skipped too.

def a(z):
    try:
        100/z
    except ZeroDivisionError:
        try:
            print('x')
        finally:
            return 42
    finally:
        return 1


In [1]: a(0)
x
Out[1]: 1

According to the documentation, it is better to handle multiple exceptions through tuples or like this:

import sys

try:
    f = open('myfile.txt')
    s = f.readline()
    i = int(s.strip())
except IOError as e:
    print "I/O error({0}): {1}".format(e.errno, e.strerror)
except ValueError:
    print "Could not convert data to an integer."
except:
    print "Unexpected error:", sys.exc_info()[0]
    raise

One thing I like to avoid is raising a new exception while handling an old one. It makes the error messages confusing to read.

For example, in my code, I originally wrote

try:
    return tuple.__getitem__(self, i)(key)
except IndexError:
    raise KeyError(key)

And I got this message.

>>> During handling of above exception, another exception occurred.

What I wanted was this:

try:
    return tuple.__getitem__(self, i)(key)
except IndexError:
    pass
raise KeyError(key)

It doesn't affect how exceptions are handled. In either block of code, a KeyError would have been caught. This is merely an issue of getting style points.


I don't think it's a matter of being pythonic or elegant. It's a matter of preventing exceptions as much as you can. Exceptions are meant to handle errors that might occur in code or events you have no control over. In this case you have full control when checking if an item is an attribute or in a dictionary, so avoid nested exceptions and stick with your second attempt.


If try-except-finally is nested inside finally block, the result from "child" finally is preserved. I have not found official expaination yet, but the following code snippet shows this behavior in Python 3.6.

def f2():
    try:
        a = 4
        raise SyntaxError
    except SyntaxError as se:
        print('log SE')
        raise se from None
    finally:
        try:
            raise ValueError
        except ValueError as ve:
            a = 5
            print('log VE')
            raise ve from None
        finally:
            return 6       
        return a

In [1]: f2()
log SE
log VE
Out[2]: 6

중첩 된 try / except에 대한 좋고 간단한 예는 다음과 같습니다.

import numpy as np

def divide(x, y):
    try:
        out = x/y
    except:
        try:
            out = np.inf * x / abs(x)
        except:
            out = np.nan
    finally:
        return out

이제 다양한 조합을 시도하면 올바른 결과를 얻을 수 있습니다.

divide(15, 3)
# 5.0

divide(15, 0)
# inf

divide(-15, 0)
# -inf

divide(0, 0)
# nan

[물론 우리는 numpy를 가지고 있으므로이 함수를 만들 필요가 없습니다]

참고 URL : https://stackoverflow.com/questions/17015230/are-nested-try-except-blocks-in-python-a-good-programming-practice

반응형