명령문 의 선택적 else
절의 의도 된 용도는 무엇입니까 try
?
명령문 의 선택적 else
절의 의도 된 용도는 무엇입니까 try
?
답변:
예외가없는 else
경우 실행이 맨 아래로 떨어지면 블록 의 명령문 이 실행됩니다 try
. 솔직히, 나는 필요를 찾지 못했습니다.
그러나 예외 처리 참고 사항 :
else 절을 사용하면 try ... except 문으로 보호되는 코드에 의해 발생하지 않은 예외를 실수로 포착하지 않기 때문에 try 절에 코드를 추가하는 것보다 낫습니다.
따라서 예를 들어을 던질 수있는 메소드가 있고 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
두 번째 호출의 오류를 잡을 것입니다. 그리고 전체 try
블록 뒤에 넣으면 항상 실행되고 finally
. 은 else
당신이 있는지 확인 할 수 있습니다
finally
블록 전에 실행 되고IOError
그 인상이 여기 잡힌되지 않습니다에요return
, continue
나 break
.
하나가 큰 사용에 이유 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
두 번째는 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"물건.
파이썬 try-else
else
try 문의 선택적 절의 의도 된 용도는 무엇입니까 ?
의도 된 용도는 처리 될 것으로 예상되는 예외가없는 경우 더 많은 코드를 실행할 수있는 컨텍스트를 갖는 것입니다.
이 컨텍스트는 실수로 예기치 않은 오류를 처리하지 않도록합니다.
그러나 때문에, 실행에 다른 절을 유발하는 정확한 조건을 이해하는 것이 중요합니다 return
, continue
그리고 break
에 대한 제어 흐름을 방해 할 수 있습니다 else
.
else
이없는 경우 문이 실행 에는 예외와에 의해 중단하지 않을 경우 return
, continue
또는 break
문.
선택적
else
절은 제어 가try
절의 끝 에서 흘러 나오는 경우에 실행됩니다 . *
(볼딩이 추가되었습니다.) 그리고 각주는 다음과 같이 읽습니다.
* 현재, 제어 예외 또는 실행의 경우를 제외하고 "끝 흘러"
return
,continue
또는break
문.
하나 이상의 선행 except 절이 필요 합니다 (grammar 참조 ). 따라서 실제로는 "시도하지 않습니다"가 아니라 "시도를 제외하고 (마지막으로)"이며 else
(및 finally
)는 선택 사항입니다.
파이썬 자습서 의도 된 사용에 정성 들여 :
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 ... except 문으로 보호되는 코드에 의해 발생하지 않은 예외를 실수로 포착하지 않기 때문에 try 절에 코드를 추가하는 것보다 낫습니다.
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가 삼키고 있습니다. 더 나쁜 것은, 올바르게 작성했지만 정리 방법에 이름이 잘못 지정된 사용자 유형이 전달되어 중간에 자동으로 실패하고 파일을 닫지 않은 상태로 두는 경우가 있습니다. 그것을 디버깅하는 행운을 빕니다.
예외가있는 경우에도 정리해야 할 때 정말 유용합니다.
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
블록 외부에서 제거 할 수 있지만 변수가 정의 된 경우 지저분한 감지가 필요합니다.
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 ... except 문으로 보호되는 코드에 의해 발생하지 않은 예외를 실수로 포착하지 않기 때문에 try 절에 코드를 추가하는 것보다 낫습니다.
파이썬 참조를 보면 예외가없는 else
후에 실행되는 것 같습니다 try
. 선택적 else 절은 제어가 try 절의 끝에서 흘러 나오는 경우에 실행됩니다. 2 else 절의 예외는 앞의 except 절에 의해 처리되지 않습니다.
파이썬으로 다이빙 하면 올바르게 이해하면 try
블록에서 모듈을 가져 오려고 시도합니다. 실패하면 예외가 발생하고 기본값을 바인딩하지만 작동하면 else
블록 으로 이동하여 필요한 것을 바인딩 하는 옵션 이 있습니다 (참조) 예제와 설명에 대한 링크).
catch
블록 에서 작업하려고하면 다른 예외가 발생할 수 있습니다 else
. 블록이 편리한 곳이라고 생각 합니다.
try
블록에서 벗어날 수 있기 때문 입니다.
그게 다야. 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
물론 발생 가능한 예외를 구별 할 수있는 경우이를 사용할 필요는 없지만 성공적인 코드에 반응하는 코드가 성공적인 코드와 동일한 예외를 발생시킬 수 있으며 두 번째 가능한 예외를 보내거나 성공하면 즉시 돌아갑니다 (제 경우 스레드를 죽일 것입니다).
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
전에 try
어쨌든 0으로 설정 하면 됩니다.
내가 생각할 수있는 사용 시나리오 중 하나는 예기치 않은 예외이며 다시 시도하면 우회 할 수 있습니다. 예를 들어 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
-statement를 제외하고는 피하고, else
명시 적으로 만들기 위해 -conditioning을 고려하십시오 .
if x > 0: return "yes"
와 if x <= 0: return "no"
. 이제 사람이 와서 말할 조건 중 하나 x > 1
를 바꾸지 만 다른 것을 바꾸는 것을 잊어 버립니다. 커밋되는 버그 수를 줄이는 방법은 무엇입니까? if else
절은 때때로 여러 줄로 구분됩니다. DRY는 실제로는 아니지만 훨씬 더 좋은 습관입니다. (더블 포스트 죄송합니다).