Przechwytywanie wyjątków w Pythonie

0

Mam pytanie, mianowicie chcę zczytać inta i w przypadku kiedy operacja się nie powiedzie przechwycić wyjątek ValueError, z tą różnicą że zamiast domyślnego komunikatu invalid literal for int() with base 10: 'regrg' chcę przekazać do konstruktora ValueError własny komunikat. Czy w poniższym kodzie dobrze to robię? Mam na myśli zagnieżdżoną instrukcję try wewnątrz instrukcji try w funkcji read_date. Chcę wiedzieć czy ta dobra jest dobra, czy istnieją sprytniejsze sposoby na to.

Przykładowy kod:

def read_date():
    valid = False
    year = None
    era = None
    while not valid:
        try:
            print('Enter a year in the format year [BCE|CE]. Note that part BCE|CE is optional.')
            print("If era won't be specified, then default value will be CE.")
            date = input('> ')
            if date.isnumeric():
                year = date
                era = Era.CE
            else:
                year = date.split()[0]
                era = date.split()[-1]
                if era == 'BCE':
                    era = Era.BCE
                elif era == 'CE':
                    era = Era.CE
                else:
                    raise ValueError('Error: invalid era. Valid choices are BCE and CE.')
            try:
                year = int(year)
            except ValueError:
                raise ValueError('Error: year must be an integer.')
            if year < 1:
                raise ValueError('Error: year must be greater than 0.')
        except ValueError as e:
            print(e)
        else:
            valid = True
    return HistoricalDate(year=year, era=era)
1

Używa się konstrukcji raise nowy_wyjatek from stary_wyjatek. Porównaj komunikaty:

>>> def foo():
...     raise ValueError("...")
... 
>>> 
>>> try:
...     foo()
... except ValueError:
...     raise ValueError("???")
... 
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
  File "<stdin>", line 2, in foo
ValueError: ...

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<stdin>", line 4, in <module>
ValueError: ???
>>>
>>>
>>>
>>> try:
...     foo()
... except ValueError as e:
...     raise ValueError("???") from e
... 
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
  File "<stdin>", line 2, in foo
ValueError: ...

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "<stdin>", line 4, in <module>
ValueError: ???
0

To masz na myśli?

def read_date():
    valid = False
    year = None
    era = None
    while not valid:
        try:
            print('Enter a year in the format year [BCE|CE]. Note that part BCE|CE is optional.')
            print("If era won't be specified, then default value will be CE.")
            date = input('> ')
            if date.isnumeric():
                year = date
                era = Era.CE
            else:
                year = date.split()[0]
                era = date.split()[-1]
                if era == 'BCE':
                    era = Era.BCE
                elif era == 'CE':
                    era = Era.CE
                else:
                    raise ValueError('Error: invalid era. Valid choices are BCE and CE.')
            try:
                year = int(year)
            except ValueError as e:
                raise ValueError('Error: year must be an integer.') from e
            if year < 1:
                raise ValueError('Error: year must be greater than 0.')
        except ValueError as e:
            print(e)
        else:
            valid = True
    return HistoricalDate(year=year, era=era)

Tak jest dobrze?

0

Mam jeszcze pytanie, co sądzisz o napisaniu scentralizowanego systemu obsługi wyjątków?

0

Niektórzy chwalą i zalecają takie podejście :)
https://owasp.org/www-project-proactive-controls/v3/en/c10-errors-exceptions
Positive Advice > "Manage exceptions in a centralized manner to avoid duplicated try/catch blocks in the code. Ensure that all unexpected behavior is correctly handled inside the application."

0
doskanoness napisał(a):

Mam jeszcze pytanie, co sądzisz o napisaniu scentralizowanego systemu obsługi wyjątków?

Zcentralizowana obsługa jest niezbędna, ale zwykle to za mało.

Zamiast robić w jednym miejscu try/catch dla każdego wyjątku:

  • bazujesz wszystkie swoje wyjątki na Exception
  • w swoich modułach które udostępniasz innym jako API
    • dajesz jeden bazowy exception per moduł bazujący na Exception - ułatwia to obsługę błędów innym
    • w każdym unikalnym wypadku stosujesz nową klasę exception bazującą na bazowym exception modułu
  • w swoich modułach prywatnych możesz używać standardowych exception lub bazujących na standardowych

Więcej o tym w poradzie 87 w Effective Python i https://doughellmann.com/posts/python-exception-handling-techniques/

1 użytkowników online, w tym zalogowanych: 0, gości: 1