else
ステートメントのオプションのtry
節の意図された使用は何ですか?
else
ブロック内のステートメントは、実行がtry
の下から外れた場合(例外がなかった場合)に実行されます。正直なところ、私は必要性を見つけたことがない。
ただし、 例外処理 には次のように記載されています。
Else節の使用は、try節に追加されたコードを追加するよりも優れています。これは、try ... exceptステートメントによって保護されているコードによって引き起こされなかった例外を誤って捕捉するのを防ぐためです。
したがって、たとえばIOError
をスローする可能性があるメソッドがあり、それが発生した例外をキャッチしたいが、最初の操作が成功した場合は他に何かしたいことがあります。don'tその操作からIOErrorをキャッチしたい場合は、次のように記述します。
try:
operation_that_can_throw_ioerror()
except IOError:
handle_the_exception_somehow()
else:
# we don't want to catch the IOError if it's raised
another_operation_that_can_throw_ioerror()
finally:
something_we_always_need_to_do()
operation_that_can_throw_ioerror
の後に単にanother_operation_that_can_throw_ioerror()
を置くと、except
は2番目の呼び出しのエラーをキャッチします。そしてそれをtry
ブロック全体の後に置くと、それは常に実行され、finally
の後までは実行されません。 else
はあなたが確かめることを可能にします
finally
ブロックの前に実行されます。IOError
sもここでつかまえられないelse
- スタイルと読みやすさを使用する理由は1つ大きなあります。例外を引き起こす可能性のあるコードを、それらを処理するコードの近くに置くことをお勧めします。たとえば、これらを比較します。
try:
from EasyDialogs import AskPassword
# 20 other lines
getpass = AskPassword
except ImportError:
getpass = default_getpass
そして
try:
from EasyDialogs import AskPassword
except ImportError:
getpass = default_getpass
else:
# 20 other lines
getpass = AskPassword
2つ目は、except
が早く戻ることができない場合、または例外を再スローする場合に適しています。可能であれば、私は書いただろう:
try:
from EasyDialogs import AskPassword
except ImportError:
getpass = default_getpass
return False # or throw Exception('something more descriptive')
# 20 other lines
getpass = AskPassword
注:最近投稿された複製 から回答をコピーしたもの なので、この「AskPassword」のものすべて。
1つの用途:例外を発生させるはずのコードをテストします。
try:
this_should_raise_TypeError()
except TypeError:
pass
except:
assert False, "Raised the wrong exception type"
else:
assert False, "Didn't raise any exception"
(このコードは実際にはより一般的なテストに抽象化されるべきです。)
Python try-else
Tryステートメントのオプションの
else
節の意図された使用は何ですか?
意図された使用はそれが扱われると予想されるところに例外がなかったなら実行するためにもっと多くのコードのための文脈を持つことです。
このコンテキストは、予期していなかったエラーを誤って処理しないようにします。
return
、continue
、およびbreak
は、else
への制御フローを中断する可能性があるため、else節が実行される正確な条件を理解することが重要です。
else
ステートメントは、noの例外がなく、return
、continue
、またはbreak
ステートメントによって割り込まれない場合に実行されます。
オプションの
else
句は、controlがtry
句の末尾から離れたときに実行されます。
(太字は付け加えた。)そして脚注はこう読みます:
*現在のところ、例外または
return
、continue
、またはbreak
ステートメントの実行を除いて、制御は「終わりから流れています」。
少なくとも1つの先行するexcept節を必要とします( 文法を参照してください )。したがって、それは実際には「try-else」ではなく、「try-except-else(-finally)」であり、else
(およびfinally
)はオプションです。
Pythonチュートリアル では、使用目的について詳しく説明しています。
Try ... exceptステートメントには、オプションのelse節があります。これが存在する場合は、except節をすべて続ける必要があります。 try句が例外を発生させない場合に実行されなければならないコードに役立ちます。例えば:
for arg in sys.argv[1:]: try: f = open(arg, 'r') except IOError: print 'cannot open', arg else: print arg, 'has', len(f.readlines()), 'lines' f.close()
Else節の使用は、try節に追加されたコードを追加するよりも優れています。これは、try ... exceptステートメントによって保護されているコードによって引き起こされなかった例外を誤って捕捉するのを防ぐためです。
else
ブロックに続くコードとtry
を区別する例エラーを処理した場合、else
ブロックは実行されません。例えば:
def handle_error():
try:
raise RuntimeError('oops!')
except RuntimeError as error:
print('handled a RuntimeError, no big deal.')
else:
print('if this prints, we had no error!') # won't print!
print('And now we have left the try block!') # will print!
そしていま、
>>> handle_error()
handled a RuntimeError, no big deal.
And now we have left the try block!
Try-except-elseは、 EAFPパターン と duck-typing を組み合わせるのに最適です。
try:
cs = x.cleanupSet
except AttributeError:
pass
else:
for v in cs:
v.cleanup()
この素朴なコードで問題ないと思うかもしれません。
try:
for v in x.cleanupSet:
v.clenaup()
except AttributeError:
pass
これは、コード内の誤った重大なバグを隠すのに最適な方法です。私はそこでクリーンアップをタイプミスしました、しかし私に知らせるであろうAttributeErrorは飲み込まれています。さらに悪いことに、それを正しく書いたとしたら、クリーンアップ・メソッドが誤った属性を持つユーザー・タイプを渡されることがあり、途中で静かに失敗してファイルをクローズしないままにしていました。幸運にもそれをデバッグすること。
たとえ例外があったとしてもそれをしなければならないクリーンアップがあるとき、私はそれが本当に役に立つと思います:
try:
data = something_that_can_go_wrong()
except Exception as e: # yes, I know that's a bad way to do it...
handle_exception(e)
else:
do_stuff(data)
finally:
clean_up()
あなたは今それを使うことを考えることができないとしても、あなたはそれを使うことがあるに違いない。想像力に溢れるサンプルです。
else
の場合:
a = [1,2,3]
try:
something = a[2]
except:
print "out of bounds"
else:
print something
else
がなければ:
try:
something = a[2]
except:
print "out of bounds"
if "something" in locals():
print something
エラーが発生しない場合は、ここで変数something
を定義します。これをtry
ブロックの外で削除することはできますが、変数が定義されている場合は厄介な検出が必要になります。
From エラーと例外#例外の処理 - docs.python.org
try ... except
ステートメントには、オプションのelse
句があります。これは、存在する場合は、句を除くすべての句の後に続ける必要があります。 try句が例外を発生させない場合に実行されなければならないコードに役立ちます。例えば:for arg in sys.argv[1:]: try: f = open(arg, 'r') except IOError: print 'cannot open', arg else: print arg, 'has', len(f.readlines()), 'lines' f.close()
Else節の使用は、try節に追加されたコードを追加するよりも優れています。これは、try ... exceptステートメントによって保護されているコードによって引き起こされなかった例外を誤って捕捉するのを防ぐためです。
PEP 380 にtry-else
のいい例があります。基本的には、アルゴリズムのさまざまな部分でさまざまな例外処理を行うことになります。
それはこのようなものです:
try:
do_init_stuff()
except:
handle_init_suff_execption()
else:
try:
do_middle_stuff()
except:
handle_middle_stuff_exception()
これにより、例外が発生した場所により近い例外処理コードを書くことができます。
Pythonリファレンス を見ると、例外がない場合はelse
がtry
の後に実行されるようです。オプションのelse節は、制御がtry節の末尾から離れたときに実行されます。 2 else節の例外は、上記のexcept節では処理されません。
python に飛び込むと、try
ブロックで正しく理解できればモジュールをインポートしようとしますが、失敗すると例外が発生してデフォルトにバインドされますしかしそれがうまくいくとき、あなたはelse
ブロックに入り、必要なものをバインドするという選択肢があります(例と説明についてはリンクを見てください)。
catch
ブロックで作業を行おうとした場合、別の例外がスローされる可能性があります - else
ブロックが便利なところだと思います。
それでおしまい。 try-except節の 'else'ブロックは、試行した操作が成功したときに(そしてそのときだけ)実行されるコードに存在します。それは使用することができ、それは悪用することができます。
try:
fp= open("configuration_file", "rb")
except EnvironmentError:
confdata= '' # it's ok if the file can't be opened
else:
confdata= fp.read()
fp.close()
# your code continues here
# working with (possibly empty) confdata
個人的には、私はそれが好きで、適切なときにそれを使います。文を意味的にグループ化します。
ほとんどの答えは、try節の中にelse節の中にその資料を入れることができない理由に集中しているようです。 try文のquestion else節... に何が良いのかというと、else節のコードがなぜの後に行なえないのかを具体的に尋ねています。 try自体はブロックされていて、その質問はこの質問に重複していますが、ここではその質問に対する明確な回答は見ていません。私は感じます https://stackoverflow.com/a/3996378/1503120 この質問に非常によく答えます。私はまた、 https://stackoverflow.com/a/22579805/1503120 でさまざまな句のさまざまな意味を説明しようとしました。
おそらく用途は次のようになります。
#debug = []
def debuglog(text, obj=None):
" Simple little logger. "
try:
debug # does global exist?
except NameError:
pass # if not, don't even bother displaying
except:
print('Unknown cause. Debug debuglog().')
else:
# debug does exist.
# Now test if you want to log this debug message
# from caller "obj"
try:
if obj in debug:
print(text) # stdout
except TypeError:
print('The global "debug" flag should be an iterable.')
except:
print('Unknown cause. Debug debuglog().')
def myfunc():
debuglog('Made it to myfunc()', myfunc)
debug = [myfunc,]
myfunc()
多分これはあなたにも使用法を導くでしょう。
データベースクエリを実行し、それらのクエリの結果を同じ種類/種類の別のデータベースに記録している状況では、try: ... else:
構文が便利です。キューに送信されたデータベースクエリをすべて扱うワーカースレッドがたくさんあるとしましょう。
#in a long running loop
try:
query = queue.get()
conn = connect_to_db(<main db>)
curs = conn.cursor()
try:
curs.execute("<some query on user input that may fail even if sanitized">)
except DBError:
logconn = connect_to_db(<logging db>)
logcurs = logconn.cursor()
logcurs.execute("<update in DB log with record of failed query")
logcurs.close()
logconn.close()
else:
#we can't put this in main try block because an error connecting
#to the logging DB would be indistinguishable from an error in
#the mainquery
#We can't put this after the whole try: except: finally: block
#because then we don't know if the query was successful or not
logconn = connect_to_db(<logging db>)
logcurs = logconn.cursor()
logcurs.execute("<update in DB log with record of successful query")
logcurs.close()
logconn.close()
#do something in response to successful query
except DBError:
#This DBError is because of a problem with the logging database, but
#we can't let that crash the whole thread over what might be a
#temporary network glitch
finally:
curs.close()
conn.close()
#other cleanup if necessary like telling the queue the task is finished
もちろん、スローされる可能性のある例外を区別できれば、これを使用する必要はありませんが、成功したコードに反応するコードが成功したピースと同じ例外をスローする可能性があり、 2番目に起こり得る例外を去るか、または成功したらすぐに戻る(これは私の場合はスレッドを殺すだろう)、そしてこれは役に立ちます。
私はelse
が間違っている可能性のある設定ファイルを扱うのに便利だとわかりました:
try:
value, unit = cfg['lock'].split()
except ValueError:
msg = 'lock monitoring config must consist of two words separated by white space'
self.log('warn', msg)
else:
# get on with lock monitoring if config is ok
lock
設定を読み取る例外はロックモニタリングを無効にし、ValueErrorsは有用な警告メッセージをログに記録します。
私が考えることができる使用シナリオの1つは予測不可能な例外です、あなたがもう一度試みるならば回避することができます。たとえば、tryブロック内の演算に乱数が含まれているとします。
while True:
try:
r = random.random()
some_operation_that_fails_for_specific_r(r)
except Exception:
continue
else:
break
ただし、例外が予測できる場合は、例外よりも事前に検証を常に選択する必要があります。しかし、すべてを予測できるわけではないので、このコードパターンにはその場所があります。
これが私がこのパターンを使うのを好むもう一つの場所です:
while data in items:
try
data = json.loads(data)
except ValueError as e:
log error
else:
# work on the `data`
else
ブロックは、すべてのexcept
ブロックで発生する機能を補完するために存在することがよくあります。
try:
test_consistency(valuable_data)
except Except1:
inconsistency_type = 1
except Except2:
inconsistency_type = 2
except:
# Something else is wrong
raise
else:
inconsistency_type = 0
"""
Process each individual inconsistency down here instead of
inside the except blocks. Use 0 to mean no inconsistency.
"""
この場合、inconsistency_type
がexcept以外の各ブロックに設定されているので、else
のエラーがない場合に動作が補完されます。
もちろん、私はこれをいつかあなた自身のコードで現れるかもしれないパターンとして説明しています。この特定のケースでは、とにかくtry
ブロックの前にinconsistency_type
を0に設定するだけです。
プログラミングロジックが辞書に与えられたキーを持つエントリがあるかどうかに依存しているとしましょう。 if... else...
構文を使ってdict.get(key)
の結果をテストすることができます。
try:
val = dic[key]
except KeyError:
do_some_stuff()
else:
do_some_stuff_with_val(val)