Pythonでtry / exceptionを1行に変換する方法はありますか?
何かのようなもの...
b = 'some variable'
a = c | b #try statement goes here
b
宣言された変数はどこにあり、c
そうではありません...したがってc
、エラーがスローされ、...にa
なりb
ます。
回答:
Pythonではtry
/except
ブロックを1行に圧縮する方法はありません。
また、他の動的言語のように、Pythonに変数が存在するかどうかを知らないのは悪いことです。より安全な方法(および一般的なスタイル)は、すべての変数を何かに設定することです。設定されない可能性がある場合は、None
最初に設定します(または0
、''
より適切な場合は、または何か)。
あなたがいる場合行うあなたが最初に興味を持っているすべての名前を割り当てるには、オプションを持っています。
最良のオプションはifステートメントです。
c = None
b = [1, 2]
if c is None:
a = b
else:
a = c
ワンライナーオプションは条件式です。
c = None
b = [1, 2]
a = c if c is not None else b
一部の人々or
はこれを行うためにの短絡動作を悪用します。これはエラーが発生しやすいので、私は決して使用しません。
c = None
b = [1, 2]
a = c or b
次の場合を考えてみましょう。
c = []
b = [1, 2]
a = c or b
この場合、a
おそらくはであるはずですが[]
、ブール値のコンテキストではfalseである[1, 2]
ため[]
です。間違っている可能性のある値がたくさんあるので、私はor
トリックを使用しません。(これは、人々がif foo:
意味するときに言うときに遭遇するのと同じ問題if foo is not None:
です。)
try
/except
ブロックの1行の構文はありません。幸いなことに、回線は安価なので、4回線のソリューションが適しています。;-)
get
例外が必要ない場合は使用しないでください。filter
代わりに使用してください。
これはひどくハックですが、デバッグ用の一連のアクションを記述したいときにプロンプトで使用しました。
exec "try: some_problematic_thing()\nexcept: problem=sys.exc_info()"
print "The problem is %s" % problem[1]
ほとんどの場合、私はno-single-line-try-except制限にまったく悩まされていませんが、実験しているときに、readlineがインタラクティブインタープリターでコードのチャンク全体を一度に呼び出すようにしたい場合は、なんとか調整できるので、このちょっとしたコツが重宝します。
あなたが達成しようとしている実際の目的のために、あなたは試みるかもしれませんlocals().get('c', b)
; 理想的には、ローカルコンテキストの代わりに実際の辞書を使用するか、設定されているかどうかに関係なく実行する前にcをNoneに割り当てる方がよいでしょう。
problem[0]
その関数が返すものを返しますか?
python3では、使用することができcontextlib.suppressを:
from contextlib import suppress
d = {}
with suppress(KeyError): d['foo']
別の方法は、コンテキストマネージャーを定義することです。
class trialContextManager:
def __enter__(self): pass
def __exit__(self, *args): return True
trial = trialContextManager()
次に、with
ステートメントを使用して、1行のエラーを無視します。
>>> 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
ランタイムエラーが発生しても例外は発生しません。のtry:
ないようなものexcept:
です。
予想される例外が限定されたpoke53280回答のバージョン。
def try_or(func, default=None, expected_exc=(Exception,)):
try:
return func()
except expected_exc:
return default
そしてそれはとして使用することができます
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
parse_float = lambda x, y=exec("def f(s):\n try:\n return float(s)\n except: return None"): f(x)
常に解決策があります。
問題は、実際にテストしようとしているdjangomodel.objects.getクエリです。データが見つからない場合、.getはエラーを返します...それはNoneを返しません(これは私を悩ませます)
次のようなものを使用します。
print("result:", try_or(lambda: model.objects.get(), '<n/a>'))
try_orは、ユーザーが定義したユーティリティ関数です。
def try_or(fn, default):
try:
return fn()
except:
return default
必要に応じて、あなたはに受け入れられた例外の種類を制限することができNameError
、AttributeError
など
あなたは使用して名前空間の辞書にアクセスすることによってそれを行うことができますvars()
、locals()
またはglobals()
あなたの状況に最も適している方、。
>>> b = 'some variable'
>>> a = vars().get('c', b)
実際に例外を管理する必要がある場合:
(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
>>>
例外がサポートされていない場合、期待どおりに発生することに注意してください。
>>> 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'
>>>
また、Exception
が指定されている場合は、以下のいずれかに一致します。
(BaseException
高いので一致しません)
>>> try_or( context, {Exception: lambda: print('exception')} )
exception
これは@surendra_benによって提供された答えのより簡単なバージョンです
a = "apple"
try: a.something_that_definitely_doesnt_exist
except: print("nope")
...
nope
with
1行で構文を使用します。
class OK(): __init__ = lambda self, isok=None: setattr(self, 'isok', isok); __enter__ = lambda self: None; __exit__ = lambda self, exc_type, exc_value, traceback: (True if not self.isok or issubclass(exc_type, self.isok) else None) if exc_type else None
エラーを無視します。
with OK(): 1/0
指定されたエラーを無視します:
with OK(ZeroDivisionError): 1/0
with OK((ZeroDivisionError, NameError)): 1/0