Czy w Pythonie jest sposób, aby zamienić try / except w pojedynczą linię?
coś jak...
b = 'some variable'
a = c | b #try statement goes here
Gdzie b
jest zadeklarowaną zmienną i c
nie jest ... więc c
zgłosi błąd i a
stanie się b
...
źródło
Czy w Pythonie jest sposób, aby zamienić try / except w pojedynczą linię?
coś jak...
b = 'some variable'
a = c | b #try statement goes here
Gdzie b
jest zadeklarowaną zmienną i c
nie jest ... więc c
zgłosi błąd i a
stanie się b
...
W Pythonie nie ma sposobu, aby skompresować try
/ except
blok do jednej linii.
Poza tym źle jest nie wiedzieć, czy w Pythonie istnieje zmienna, tak jak w innych dynamicznych językach. Bezpieczniejszym sposobem (i dominującym stylem) jest ustawienie na coś wszystkich zmiennych. Jeśli mogą nie zostać ustawione, ustaw je jako None
pierwsze ( 0
lub ''
lub coś, jeśli jest to bardziej odpowiednie).
Jeśli zrobić przypisać wszystkie nazwiska jesteś zainteresowany po pierwsze, masz opcje.
Najlepszą opcją jest instrukcja if.
c = None
b = [1, 2]
if c is None:
a = b
else:
a = c
Opcja jednowierszowa jest wyrażeniem warunkowym.
c = None
b = [1, 2]
a = c if c is not None else b
Niektórzy ludzie nadużywają w tym celu zachowania zwarciowego or
. Jest to podatne na błędy, więc nigdy go nie używam.
c = None
b = [1, 2]
a = c or b
Rozważ następujący przypadek:
c = []
b = [1, 2]
a = c or b
W tym przypadku a
prawdopodobnie powinno być []
, ale dzieje się tak , [1, 2]
ponieważ []
jest fałszywe w kontekście logicznym. Ponieważ istnieje wiele wartości, które mogą być fałszywe, nie używam or
sztuczki. (Jest to ten sam problem, na który napotykają ludzie, kiedy mówią, if foo:
kiedy mają na myśli if foo is not None:
).
try
/except
. Na szczęście linie są tanie, więc rozwiązanie 4-liniowe powinno działać dla Ciebie. ;-)get
jeśli nie chcesz wyjątku. Użyjfilter
zamiast tego.To strasznie hackerskie, ale użyłem go w zachęcie, gdy chciałem napisać sekwencję działań do debugowania:
exec "try: some_problematic_thing()\nexcept: problem=sys.exc_info()" print "The problem is %s" % problem[1]
W większości przypadków w ogóle nie przeszkadza mi ograniczenie bez jednej linii-try-z wyjątkiem, ale kiedy tylko eksperymentuję i chcę, aby readline przypomniało sobie cały fragment kodu naraz w interaktywnym interpreteru, więc że mogę to jakoś dostosować, ta mała sztuczka się przydaje.
W celu, jaki chcesz osiągnąć, możesz spróbować
locals().get('c', b)
; Idealnie byłoby lepiej użyć prawdziwego słownika zamiast lokalnego kontekstu lub po prostu przypisać c do Brak przed uruchomieniem tego, co może go ustawić lub nie.źródło
problem[0]
wrócić co zwracającej funkcji?W pythonie3 możesz użyć contextlib.suppress :
from contextlib import suppress d = {} with suppress(KeyError): d['foo']
źródło
Innym sposobem jest zdefiniowanie menedżera kontekstu:
class trialContextManager: def __enter__(self): pass def __exit__(self, *args): return True trial = trialContextManager()
Następnie użyj
with
instrukcji, aby zignorować błędy w jednym wierszu:>>> with trial: a = 5 # will be executed normally >>> with trial: a = 1 / 0 # will be not executed and no exception is raised >>> print a 5
Żaden wyjątek nie zostanie zgłoszony w przypadku błędu w czasie wykonywania. To jest jak
try:
bezexcept:
.źródło
Wersja odpowiedzi poke53280 z ograniczonymi oczekiwanymi wyjątkami.
def try_or(func, default=None, expected_exc=(Exception,)): try: return func() except expected_exc: return default
i może być używany jako
In [2]: try_or(lambda: 1/2, default=float('nan')) Out[2]: 0.5 In [3]: try_or(lambda: 1/0, default=float('nan'), expected_exc=(ArithmeticError,)) Out[3]: nan In [4]: try_or(lambda: "1"/0, default=float('nan'), expected_exc=(ArithmeticError,)) --------------------------------------------------------------------------- TypeError Traceback (most recent call last) [your traceback here] TypeError: unsupported operand type(s) for /: 'str' and 'int' In [5]: try_or(lambda: "1"/0, default=float('nan'), expected_exc=(ArithmeticError, TypeError)) Out[5]: nan
źródło
parse_float = lambda x, y=exec("def f(s):\n try:\n return float(s)\n except: return None"): f(x)
Zawsze jest rozwiązanie.
źródło
Użyj czegoś takiego:
print("result:", try_or(lambda: model.objects.get(), '<n/a>'))
Gdzie try_or to zdefiniowana przez Ciebie funkcja narzędziowa:
def try_or(fn, default): try: return fn() except: return default
Opcjonalnie można ograniczyć Akceptowane formaty wyjątek
NameError
,AttributeError
itpźródło
Można to zrobić, korzystając z dict namespace użyciu
vars()
,locals()
lubglobals()
, w zależności co jest najbardziej odpowiednie dla danej sytuacji.>>> b = 'some variable' >>> a = vars().get('c', b)
źródło
Co powiesz na użycie dwóch linii. czy to jest w porządku ?
>>> try: a = 3; b= 0; c = a / b ... except : print('not possible'); print('zero division error') ... not possible zero division error
źródło
Wspomniałeś, że używasz django. Jeśli ma to sens dla tego, co robisz, możesz użyć:
created
będzie True lub False. Może to ci pomoże.źródło
jeśli chcesz faktycznie zarządzać wyjątkami:
(zmodyfikowane na podstawie odpowiedzi poke53280)
>>> def try_or(fn, exceptions: dict = {}): try: return fn() except Exception as ei: for e in ei.__class__.__mro__[:-1]: if e in exceptions: return exceptions[e]() else: raise >>> def context(): return 1 + None >>> try_or( context, {TypeError: lambda: print('TypeError exception')} ) TypeError exception >>>
zauważ, że jeśli wyjątek nie jest obsługiwany, zostanie podniesiony zgodnie z oczekiwaniami:
>>> try_or( context, {ValueError: lambda: print('ValueError exception')} ) Traceback (most recent call last): File "<pyshell#57>", line 1, in <module> try_or( context, {ValueError: lambda: print('ValueError exception')} ) File "<pyshell#38>", line 3, in try_or return fn() File "<pyshell#56>", line 2, in context return 1 + None TypeError: unsupported operand type(s) for +: 'int' and 'NoneType' >>>
również jeśli
Exception
zostanie podane, będzie pasować do wszystkiego poniżej.(
BaseException
jest wyższa, więc nie będzie pasować)>>> try_or( context, {Exception: lambda: print('exception')} ) exception
źródło
Działa na Pythonie3, inspirowanym twórczością Waltera Mundta
exec("try:some_problematic_thing()\nexcept:pass")
Dla wielu linii w jedną linię
exec("try:\n\tprint('FirstLineOk')\n\tsome_problematic_thing()\n\tprint('ThirdLineNotTriggerd')\nexcept:pass")
Ps: Exec jest niebezpieczny w przypadku danych, nad którymi nie masz kontroli.
źródło