Podczas korzystania z PyCharm IDE użycie typu except:
bez wyjątku wyzwala przypomnienie ze środowiska IDE, że ta klauzula wyjątku jest Too broad
.
Czy powinienem ignorować tę radę? A może Pythonic zawsze określa typ wyjątku?
Podczas korzystania z PyCharm IDE użycie typu except:
bez wyjątku wyzwala przypomnienie ze środowiska IDE, że ta klauzula wyjątku jest Too broad
.
Czy powinienem ignorować tę radę? A może Pythonic zawsze określa typ wyjątku?
Odpowiedzi:
Prawie zawsze lepiej jest określić jawny typ wyjątku. Jeśli użyjesz except:
klauzuli naked , możesz w końcu złapać wyjątki inne niż te, których się spodziewasz - może to ukryć błędy lub utrudnić debugowanie programów, które nie robią tego, czego się spodziewasz.
Na przykład, jeśli wstawiasz wiersz do bazy danych, możesz chcieć złapać wyjątek wskazujący, że wiersz już istnieje, aby można było przeprowadzić aktualizację.
try:
insert(connection, data)
except:
update(connection, data)
Jeśli określisz bare except:
, złapiesz również błąd gniazda wskazujący, że serwer bazy danych przewrócił się. Najlepiej jest wychwytywać tylko wyjątki, które wiesz, jak sobie z nimi radzić - często lepiej jest, aby program zakończył się niepowodzeniem w momencie wystąpienia wyjątku, niż kontynuował, ale zachowywał się w dziwny, nieoczekiwany sposób.
Jeden przypadek, w którym możesz chcieć użyć bare, except:
znajduje się na najwyższym poziomie programu, który musisz zawsze uruchomić, na przykład serwera sieciowego. Ale wtedy musisz bardzo uważać, aby rejestrować wyjątki, w przeciwnym razie niemożliwe będzie ustalenie, co się dzieje. Zasadniczo w programie powinno być co najwyżej jedno miejsce, które to robi.
Konsekwencją tego wszystkiego jest to, że twój kod nigdy nie powinien działać, raise Exception('some message')
ponieważ zmusza kod klienta do użycia except:
(lub except Exception:
co jest prawie tak samo złe). Powinieneś zdefiniować wyjątek specyficzny dla problemu, który chcesz zasygnalizować (może dziedziczyć z jakiejś wbudowanej podklasy wyjątków, takiej jak ValueError
lub TypeError
). Lub powinieneś zgłosić konkretny wbudowany wyjątek. Dzięki temu użytkownicy Twojego kodu mogą ostrożnie wychwytywać tylko wyjątki, które chcą obsłużyć.
except:
również łapie (między innymi) NameError
i AttributeError
, więc jeśli źle przeliterujesz coś w try
bloku (np. Twoja funkcja "wstaw" jest faktycznie wywoływana, insert_one
ponieważ ktoś nie cenił spójności tak bardzo, jak powinien), zawsze po cichu próbuje update()
.
main()
)?
except Exception:
złapie NameError
i AttributeError
też. Co sprawia, że gołą except:
tak złe jest to, że rzeczy, które łapie ma żadnego interesu złowieniu, na przykład SystemExit
(podniesione podczas rozmowy exit
lub sys.exit
, a teraz już zapobiec zamierzony exit) i KeyboardInterrupt
(ponownie, jeśli przeboju użytkownika Ctrl-C
, to prawdopodobnie nie chcą biec dalej tylko po to, by im złość). Tylko to ostatnie ma sens, aby złapać i powinno być złapane wyraźnie. Przynajmniej except Exception:
pozwól tym dwóm rozmnażać się normalnie.
Nie należy ignorować rady udzielonej przez tłumacza.
Z przewodnika po stylu PEP-8 dla Pythona:
Podczas wychwytywania wyjątków należy wspomnieć o określonych wyjątkach, jeśli to możliwe, zamiast używać czystej klauzuli except :.
Na przykład użyj:
try:
import platform_specific_module
except ImportError:
platform_specific_module = None
Sama klauzula except: przechwytuje wyjątki SystemExit i KeyboardInterrupt, utrudniając przerwanie programu za pomocą Control-C i może maskować inne problemy. Jeśli chcesz wyłapać wszystkie wyjątki, które sygnalizują błędy programu, użyj wyjątku Exception: (bare except jest równoważne z wyjątkiem BaseException :).
Dobrą praktyczną zasadą jest ograniczenie używania samych klauzul „z wyjątkiem” do dwóch przypadków:
Jeśli program obsługi wyjątków będzie drukował lub logował śledzenie; przynajmniej użytkownik będzie świadomy wystąpienia błędu. Jeśli kod musi wykonać pewne prace porządkowe, ale pozwala na propagację wyjątku w górę za pomocą funkcji raise. spróbuj ... wreszcie może być lepszym sposobem załatwienia tej sprawy.
Nie dotyczy to Pythona.
Istotą wyjątków jest zajęcie się problemem jak najbliżej miejsca jego powstania.
Zachowujesz więc kod, który w wyjątkowych okolicznościach może wywołać problem i rozwiązanie „obok” siebie.
Chodzi o to, że nie możesz znać wszystkich wyjątków, które mogą zostać wyrzucone przez fragment kodu. Jedyne, co możesz wiedzieć, to to, że jeśli jest to, powiedzmy, wyjątek nie znaleziono pliku, możesz go przechwycić i poprosić użytkownika o uzyskanie takiego, który wykonuje lub anuluje tę funkcję.
Jeśli umieścisz spróbuj złapać, to bez względu na to, jaki problem wystąpił w twojej procedurze pliku (tylko do odczytu, uprawnienia, UAC, nie do końca pdf, itp.), Każdy z nich wpadnie do twojego pliku nie znaleziono catch, a twój użytkownik krzyczy „ale jest, ten kod jest gówniany”
Teraz jest kilka sytuacji, w których możesz złapać wszystko, ale należy je wybierać świadomie.
Są przechwytywane, cofają jakąś akcję lokalną (taką jak tworzenie lub blokowanie zasobu (na przykład otwieranie pliku na dysku w celu zapisu), a następnie ponownie zgłaszasz wyjątek, aby zająć się nim na wyższym poziomie)
Drugi ty nie obchodzi cię, dlaczego poszło źle. Na przykład drukowanie. Możesz mieć cały haczyk, aby powiedzieć, że jest jakiś problem z twoją drukarką, napraw go i nie zabijaj aplikacji z tego powodu. Podobnie na próżno, gdyby twój kod wykonywał serię oddzielnych zadań używając jakiegoś harmonogramu, nie chciałbyś, żeby cała rzecz umarła, ponieważ jedno z zadań się nie powiodło.
Uwaga Jeśli wykonasz powyższe, nie mogę polecić jakiegoś rodzaju rejestrowania wyjątków, np. Spróbuj złapać koniec dziennika, wystarczająco wysoko.
Z tym też złapiesz np. Control-C, więc nie rób tego, chyba że ponownie nim „rzucisz”. Jednak w takim przypadku powinieneś raczej użyć „w końcu”.
Zawsze określić typ wyjątku, istnieje wiele rodzajów nie chcesz złapać, jak SyntaxError
, KeyboardInterrupt
, MemoryError
itp
except Exception:
omija powyższe typy, których nie chcemy złapać?
except Exception
jest w porządku.
except Exception
łapie SyntaxError
i MemoryError
ponieważ jest to ich klasa bazowa. KeyboardInterrupt
, SystemExit
(podniesione przez sys.exit()
) nie są przechwytywane (są to bezpośrednie podklasy BaseException)
Oto miejsca, w których używam, z wyjątkiem bez typu
To jest główne zastosowanie w moim kodzie dla niezaznaczonych wyjątków
Zawsze to dodaję, aby kod produkcyjny nie wylewał śladów stosu
Mam na to dwa sposoby:
Wolę to w ten sposób, łatwiej jest mi wykryć, które wyjątki powinny zostać odpowiednio przechwycone: „widzę” problem lepiej, gdy wyjątek niższego poziomu jest rejestrowany przez wyższy poziom
Niektórzy współpracownicy wolą ten sposób, ponieważ zachowuje on wyjątki niższego poziomu w funkcjach niższego poziomu, do których „należą”.
Spróbuj tego:
try:
#code
except ValueError:
pass
Odpowiedź dostałem z tego linku, czy ktoś jeszcze napotkał ten problem Sprawdź to