ステートメントのオプションのelse
句の使用目的は何try
ですか?
ステートメントのオプションのelse
句の使用目的は何try
ですか?
回答:
else
ブロック内のステートメントは、try
例外が発生しなかった場合、実行が一番下に落ちた場合に実行されます。正直なところ、必要はありませんでした。
ただし、例外処理には次の点に注意してください。
else ...句を使用すると、try ...句にコードが追加されていないため、try ... exceptステートメントで保護されているコードで発生しなかった例外を誤ってキャッチすることがなくなります。
あなたは、例えば、投げることができ方法を持っているのであれば、IOError
何か他のものを、そしてあなたはそれが提起例外をキャッチしたいのですが、そこのあなたは、最初の操作が成功した場合に何をしたい、とあなたがいないから例外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()
あなただけ置く場合はanother_operation_that_can_throw_ioerror()
後にoperation_that_can_throw_ioerror
、except
2番目の呼び出しのエラーをキャッチします。そして、try
ブロック全体の後に置くと、常に実行され、の後まで実行されませんfinally
。else
あなたが確認してくださいすることができます
finally
ブロックの前に実行され、IOError
sはここではキャッチされませんreturn
、continue
かbreak
。
使用する大きな理由が1つありelse
ます。スタイルと読みやすさです。一般に、例外を引き起こす可能性のあるコードは、それらを処理するコードの近くに置くことをお勧めします。たとえば、これらを比較します。
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」に関するものすべて。
Pythonトライエルス
else
tryステートメントのオプションの句の使用目的は何ですか?
意図された用途は、処理されるはずの例外がなかった場合に実行するコードを増やすためのコンテキストを持つことです。
このコンテキストにより、予期しないエラーを誤って処理することが回避されます。
ただし、、、およびがへの制御フローを中断する可能性があるためreturn
、else句を実行させる正確な条件を理解することが重要です。continue
break
else
else
存在しない場合のステートメントが実行一切の例外とによって中断されていない場合return
、continue
またはbreak
声明。
オプションの
else
句は、制御が句の終わりから流れ出した場合に実行され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パターンとダックタイピングを組み合わせるのに最適です。
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が飲み込まれています。さらに悪いことに、正しく記述したが、クリーンアップメソッドに誤った名前の属性を持つユーザータイプが渡されたため、途中で警告なしに失敗し、ファイルが閉じられていない場合はどうなりますか?これをデバッグして頑張ってください。
現時点ではその使用法を考えることはできませんが、それを使用する必要があるに違いありません。これは想像力に欠けるサンプルです:
と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
ブロックの外で削除することはできますが、変数が定義されている場合は乱雑な検出が必要になります。
something = a[2]; print something
try:ブロック内の何が問題になっていますか?
エラーと例外から#例外の処理-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ステートメントで保護されているコードで発生しなかった例外を誤ってキャッチすることがなくなります。
Pythonのリファレンスを見ると、例外がないときにelse
実行されているようですtry
。オプションのelse句は、制御がtry句の終わりから流れ出した場合に実行されます。2 else句の例外は、先行するexcept句では処理されません。
Pythonに飛び込むには、私が正しく理解している場合、try
ブロックでモジュールをインポートしようとする例があります。それが失敗すると、例外が発生してデフォルトがバインドされますが、機能する場合は、else
ブロックに移動して必要なものをバインドするオプションがあります(例と説明のリンク)。
catch
ブロックで作業しようとすると、別の例外がスローされる可能性があります-ここでelse
ブロックが便利になると思います。
try
ブロックの外に戻ることができるため、もう1つの違いです。
それでおしまい。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
個人的には気に入っており、必要に応じて利用しています。意味的にステートメントをグループ化します。
おそらく用途は次のとおりです。
#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
ブロックは、多くの場合、すべての中で発生した機能を補完するために存在することができます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
はブロック以外の各ブロックで設定されるため、のエラーのない場合の動作が補完されelse
ます。
もちろん、私はこれをいつかあなた自身のコードで現れるかもしれないパターンとして説明しています。この特定のケースでは、とにかくブロックのinconsistency_type
前に0に設定しtry
ます。
私が考えることができる使用シナリオの1つは、予測できない例外であり、再試行すると回避できます。たとえば、tryブロックの操作に乱数が含まれる場合:
while True:
try:
r = random.random()
some_operation_that_fails_for_specific_r(r)
except Exception:
continue
else:
break
ただし、例外を予測できる場合は、例外よりも常に事前に検証を選択する必要があります。ただし、すべてを予測できるわけではないので、このコードパターンはその場所にあります。
break
内部に置くことtry
で最後に行うことができます、それはよりきれいなIMOです、そしてあなたは必要としませんelse
。また、これcontinue
は実際には必要ありませんpass
。
私を発見した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は有用な警告メッセージをログに記録します。
私は、DBセッションを処理するときに簡単に思える別の使用例を追加します。
# getting a DB connection
conn = db.engine.connect()
# and binding to a DB session
session = db.get_session(bind=conn)
try:
# we build the query to DB
q = session.query(MyTable).filter(MyTable.col1 == 'query_val')
# i.e retrieve one row
data_set = q.one_or_none()
# return results
return [{'col1': data_set.col1, 'col2': data_set.col2, ...}]
except:
# here we make sure to rollback the transaction,
# handy when we update stuff into DB
session.rollback()
raise
else:
# when no errors then we can commit DB changes
session.commit()
finally:
# and finally we can close the session
session.close()
else:
ブロックは、混乱と(ほぼ)役に立ちません。これはfor
and while
ステートメントの一部でもあります。
実際、if
ステートメントでさえ、else:
見つけるのが非常に難しいバグを作成する本当にひどい方法で悪用される可能性があります。
このことを考慮。
if a < 10:
# condition stated explicitly
elif a > 10 and b < 10:
# condition confusing but at least explicit
else:
# Exactly what is true here?
# Can be hard to reason out what condition is true
についてよく考えてくださいelse:
。一般的に問題です。- if
ステートメント以外は避け、else
-条件を文書化して明示的にすることを検討してください。
if x > 0: return "yes"
とif x <= 0: return "no"
。今、人が来て、言うべき条件の1つを変更しますx > 1
が、他の条件を変更するのを忘れます。コミットされるバグの数を減らすことはどうですか。if else
句は、多くの場合、行が離れています。DRYは良い習慣です。(二重ポストのため申し訳ありません)。