8. ìë¬ì ìì¸Â¶
ì§ê¸ê¹ì§ ìë¬ ë©ìì§ê° ì¸ê¸ëì§ë ììì§ë§, ìì ë¤ì ì§ì í´ë³´ìë¤ë©´ ìë§ë ëªëª ê°ë¥¼ ë³´ìì ê²ì ëë¤. (ì ì´ë) ë ê°ì§ 구ë³ëë ìë¬ë¤ì´ ììµëë¤; ë¬¸ë² ìë¬ ì ìì¸.
8.1. ë¬¸ë² ìë¬Â¶
ë¬¸ë² ìë¬ë, íì± ìë¬ë¼ê³ ë ìë ¤ì ¸ ììµëë¤, ìë§ë ì¬ë¬ë¶ì´ íì´ì¬ì ë°°ì°ê³ ìë ëììë ê°ì¥ ì주 ë§ëë ì¢ ë¥ì ë¶íì¼ ê²ì ëë¤:
>>> while True print('Hello world')
File "<stdin>", line 1
while True print('Hello world')
^^^^^
SyntaxError: invalid syntax
íìë 문ì ê° ëë ì¤ì ë¤ì ë³´ì¬ì£¼ê³ ì¤ìì ìë¬ê° ê°ì§ë ìì¹ë¥¼ ê°ë¦¬í¤ë ìì íì´í를 íìí©ëë¤. ì´ ìì¹ê° íì ìì í´ì¼ í ìì¹ë ìëì ì ìíììì¤. ì´ ììì, ìë¬ë í¨ì print() ìì ê°ì§ëìëë°, ë°ë¡ ìì ì½ë¡ (':') ì´ ë¹ ì ¸ì기 ë문ì
ëë¤.
íì¼ ì´ë¦(ì°ë¦¬ ìììë <stdin>)ê³¼ ì¤ ë²í¸ê° ì¸ìëì´ì, ì
ë ¥ì´ íì¼ë¡ë¶í° ì¬ ë ì°¾ì ì ìëë¡ í©ëë¤.
8.2. ìì¸Â¶
문ì¥ì´ë ííìì´ ë¬¸ë²ì ì¼ë¡ ì¬ë°ë¥´ë¤ í ì§ë¼ë, ì¤ííë ¤ê³ íë©´ ìë¬ë¥¼ ì¼ì¼í¬ ì ììµëë¤. ì¤í ì¤ì ê°ì§ëë ìë¬ë¤ì ìì¸ ë¼ê³ ë¶ë¥´ê³ 무조건 ì¹ëª ì ì´ì§ë ììµëë¤: íì´ì¬ íë¡ê·¸ë¨ìì ì´ê²ë¤ì ì´ë»ê² ë¤ë£¨ëì§ ê³§ ë°°ì°ê² ë©ëë¤. íì§ë§ ëë¶ë¶ì ìì¸ë íë¡ê·¸ë¨ì´ ì²ë¦¬íì§ ììì, ì¬ê¸°ìì ë³¼ ì ìë¯ì´ ìë¬ ë©ìì§ë¥¼ ë§ëëë¤:
>>> 10 * (1/0)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
10 * (1/0)
~^~
ZeroDivisionError: division by zero
>>> 4 + spam*3
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
4 + spam*3
^^^^
NameError: name 'spam' is not defined
>>> '2' + 2
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
'2' + 2
~~~~^~~
TypeError: can only concatenate str (not "int") to str
ìë¬ ë©ìì§ì ë§ì§ë§ ì¤ì ì´ë¤ ì¼ì´ ì¼ì´ë¬ëì§ ìë ¤ì¤ëë¤. ìì¸ë ì¬ë¬ íì¼ë¡ ëíëê³ , íì´ ë©ìì§ ì¼ë¶ë¡ ì¸ìë©ëë¤: ì´ ìììì íì ZeroDivisionError, NameError, TypeError ì
ëë¤. ìì¸ íì¼ë¡ ì¸ìë 문ìì´ì ë°ìí ë´ì¥ ìì¸ì ì´ë¦ì
ëë¤. ì´ê²ì 모ë ë´ì¥ ìì¸ë¤ì ê²½ì°ë íì ì°¸ì´ì§ë§, ì¬ì©ì ì ì ìì¸ì ê²½ì°ë (í¸ë¦¬í ê´ë¡ììë ë¶êµ¬íê³ ) ê¼ ê·¸ë´ íìë ììµëë¤. íì¤ ìì¸ ì´ë¦ì ë´ì¥ ìë³ìì
ëë¤ (ìì½ í¤ìëê° ìëëë¤).
ì¤ì ëë¨¸ì§ ë¶ë¶ì ìì¸ì íê³¼ ìì¸ì 기ë°ì ë ìì¸ ëª ì¸ë¥¼ ì ê³µí©ëë¤.
ìë¬ ë©ìì§ì ìë¶ë¶ì ì¤í í¸ë ì´ì¤ì ííë¡ ìì¸ê° ì¼ì´ë ìì¹ì 문맥ì ë³´ì¬ì¤ëë¤. ì¼ë°ì ì¼ë¡ ìì¤ì ì¤ë¤ì ëì´íë ì¤í í¸ë ì´ì¤ë¥¼ í¬í¨íê³ ììµëë¤; íì§ë§, íì¤ ì ë ¥ìì ì½ì´ ë¤ì¸ ì¤ë¤ì íìíì§ ììµëë¤.
ë´ì¥ ìì¸ ë ë´ì¥ ìì¸ë¤ê³¼ ê·¸ ë¤ì ì미를 ëì´íê³ ììµëë¤.
8.3. ìì¸ ì²ë¦¬í기¶
ì íí ìì¸ë¥¼ ì²ë¦¬íë íë¡ê·¸ë¨ì ë§ëë ê²ì´ ê°ë¥í©ëë¤. ë¤ì ì를 ë³´ë©´, ì¬ë°ë¥¼ ì ìê° ì
ë ¥ë ëê¹ì§ ì¬ì©ììê² ì
ë ¥ì ìì²íì§ë§, ì¬ì©ìê° íë¡ê·¸ë¨ì ì¸í°ë½í¸ íë ê²ì íì©í©ëë¤ (Control-C ë ê·¸ ì¸ì ì´ì ì²´ì ê° ì§ìíë ê²ì ì¬ì©í´ì); ì¬ì©ìê° ë§ë ì¸í°ë½í¸ë KeyboardInterrupt ìì¸ë¥¼ ì¼ì¼í¤ë ííë¡ ëíë¨ì ì ìíì¸ì.
>>> while True:
... try:
... x = int(input("Please enter a number: "))
... break
... except ValueError:
... print("Oops! That was no valid number. Try again...")
...
try 문ì ë¤ìê³¼ ê°ì´ ëìí©ëë¤.
먼ì , try ì (
tryìexceptì¬ì´ì 문ì¥ë¤) ì´ ì¤íë©ëë¤.ìì¸ê° ë°ìíì§ ìì¼ë©´, except ì ì ê±´ëë°ê³
try문ì ì¤íì ì¢ ë£ë©ëë¤.tryì ì ì¤ííë ëì ìì¸ê° ë°ìíë©´, ì ì ë¨ì ë¶ë¶ë¤ì ê±´ëëëë¤. ê·¸ë° ë¤ì, íì´exceptí¤ìë ë¤ì ì¤ë ìì¸ ì´ë¦ê³¼ 매ì¹ëë©´, ê·¸ except ì ì´ ì¤íëê³ , ê·¸ë° ë¤ì ì¤íì try/except ë¸ë¡ ë¤ë¡ ì´ì´ì§ëë¤.except ì ì ìë ìì¸ ì´ë¦ë¤ê³¼ 매ì¹ëì§ ìë ìì¸ê° ë°ìíë©´, ì¸ë¶ì ìë
try문ì¼ë¡ ì ë¬ë©ëë¤; ì²ë¦¬ê¸°ê° ë°ê²¬ëì§ ìì¼ë©´, ì²ë¦¬ëì§ ìì ìì¸ ì´ê³ ìë¬ ë©ìì§ë¥¼ ì¶ë ¥íë©´ì ì¤íì´ ë©ì¶¥ëë¤.
A try statement may have more than one except clause, to specify
handlers for different exceptions. At most one handler will be executed.
Handlers only handle exceptions that occur in the corresponding try clause,
not in other handlers of the same try statement. An except clause
may name multiple exceptions, for example:
... except RuntimeError, TypeError, NameError:
... pass
except ì ì ìë í´ëì¤ë í´ë¹ í´ëì¤ ìì²´ë ìì í´ëì¤ì ì¸ì¤í´ì¤ì¸ ìì¸ì 매ì¹ë©ëë¤ (íì§ë§ ë¤ë¥¸ ë°©ìì¼ë¡ë 매ì¹ëì§ ììµëë¤ â ìì í´ëì¤ë¥¼ ëì´í except ì ì ë² ì´ì¤ í´ëì¤ì ì¸ì¤í´ì¤ì 매ì¹ëì§ ììµëë¤). ì를 ë¤ì´, ë¤ìê³¼ ê°ì ì½ëë B, C, D를 ê·¸ ììëë¡ ì¸ìí©ëë¤:
class B(Exception):
pass
class C(B):
pass
class D(C):
pass
for cls in [B, C, D]:
try:
raise cls()
except D:
print("D")
except C:
print("C")
except B:
print("B")
except ì ì´ ë¤ì§íë©´ (except B ê° ì²ìì ì¤ëë¡), B, B, B를 ì¸ìíê² ë¨ì 주ìíì¸ì â ì²ìì¼ë¡ 매ì¹ëë except ì ì´ ì¤íë©ëë¤.
ìì¸ê° ë°ìí ë, ì°ê´ë ê°ì ê°ì§ ì ìëë°, ìì¸ì ì¸ì ë¼ê³ ë ìë ¤ì ¸ ììµëë¤. ì¸ìì ì¡´ì¬ì íì ìì¸ íì ìì¡´ì ì ëë¤.
The except clause may specify a variable after the exception name. The
variable is bound to the exception instance which typically has an args
attribute that stores the arguments. For convenience, builtin exception
types define __str__() to print all the arguments without explicitly
accessing .args.
>>> try:
... raise Exception('spam', 'eggs')
... except Exception as inst:
... print(type(inst)) # ìì¸ í
... print(inst.args) # .args ì ì ì¥ë ì¸ìë¤
... print(inst) # __str__ ë args ê° ì§ì ì¸ìë ì ìê²í©ëë¤,
... # íì§ë§ ìì¸ ìë¸ í´ëì¤ê° ì¬ì ìí ì ììµëë¤
... x, y = inst.args # args 를 ì¸í©í©ëë¤
... print('x =', x)
... print('y =', y)
...
<class 'Exception'>
('spam', 'eggs')
('spam', 'eggs')
x = spam
y = eggs
ìì¸ì __str__() ì¶ë ¥ì´ ì²ë¦¬ëì§ ìì ìì¸ ë©ìì§ì ë§ì§ë§ ë¶ë¶(âìì¸ ëª
ì¸â)ì ì¸ìë©ëë¤.
BaseException is the common base class of all exceptions. One of its
subclasses, Exception, is the base class of all the non-fatal exceptions.
Exceptions which are not subclasses of Exception are not typically
handled, because they are used to indicate that the program should terminate.
They include SystemExit which is raised by sys.exit() and
KeyboardInterrupt which is raised when a user wishes to interrupt
the program.
Exception can be used as a wildcard that catches (almost) everything.
However, it is good practice to be as specific as possible with the types
of exceptions that we intend to handle, and to allow any unexpected
exceptions to propagate on.
The most common pattern for handling Exception is to print or log
the exception and then re-raise it (allowing a caller to handle the
exception as well):
import sys
try:
f = open('myfile.txt')
s = f.readline()
i = int(s.strip())
except OSError as err:
print("OS error:", err)
except ValueError:
print("Could not convert data to an integer.")
except Exception as err:
print(f"Unexpected {err=}, {type(err)=}")
raise
try ⦠except 문ì ì íì ì¸ else ì ì ê°ëë°, ìë¤ë©´ 모ë except ì ë¤ììì¼ í©ëë¤. try ì ì´ ìì¸ë¥¼ ì¼ì¼í¤ì§ ìì ë ì¤íëì´ì¼ë§ íë ì½ëì ì ì©í©ëë¤. ì를 ë¤ì´:
for arg in sys.argv[1:]:
try:
f = open(arg, 'r')
except OSError:
print('cannot open', arg)
else:
print(arg, 'has', len(f.readlines()), 'lines')
f.close()
else ì ì ì¬ì©ì´ try ì ì ì½ë를 ì¶ê°íë ê²ë³´ë¤ ì¢ìë°, try ⦠except 문ì ìí´ ë³´í¸ëê³ ìë ì½ëê° ì¼ì¼í¤ì§ ìì ìì¸ë¥¼ ì°ì°í ì¡ê² ëë ê²ì ë°©ì§í기 ë문ì
ëë¤.
ìì¸ ì²ë¦¬ê¸°ë try ì ì ì§ì ë±ì¥íë ìì¸ë¿ë§ ìëë¼, try ì ìì (ê°ì ì ì¼ë¡ë¼ë) í¸ì¶ëë ë´ë¶ í¨ìë¤ìì ë°ìíë ìì¸ë¤ë ì²ë¦¬í©ëë¤. ì를 ë¤ì´:
>>> def this_fails():
... x = 1/0
...
>>> try:
... this_fails()
... except ZeroDivisionError as err:
... print('Handling run-time error:', err)
...
Handling run-time error: division by zero
8.4. ìì¸ ì¼ì¼í¤ê¸°Â¶
raise 문ì íë¡ê·¸ëë¨¸ê° ì§ì í ìì¸ê° ë°ìíëë¡ ê°ì í ì ìê² í©ëë¤. ì를 ë¤ì´:
>>> raise NameError('HiThere')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
raise NameError('HiThere')
NameError: HiThere
raise ì ì ê³µíë ë¨ì¼ ì¸ìë ë°ììí¬ ìì¸ë¥¼ ê°ë¦¬íµëë¤. ìì¸ ì¸ì¤í´ì¤ì´ê±°ë ìì¸ í´ëì¤ (BaseException ì ê³ì¹íë í´ëì¤, ê°ë ¹ Exceptionì´ë ê·¸ ìë¸ í´ëì¤) ì´ì´ì¼ í©ëë¤. ìì¸ í´ëì¤ê° ì ë¬ëë©´, 묵ìì ì¼ë¡ ì¸ì ìì´ ìì±ì를 í¸ì¶í´ì ì¸ì¤í´ì¤ë¥¼ ë§ëëë¤:
raise ValueError # 'raise ValueError()' ì ì¤ì íí
ë§ì½ ìì¸ê° ë°ìíëì§ë ììì¼ íì§ë§ ì²ë¦¬íê³ ì¶ì§ë ìë¤ë©´, ë ê°ë¨í ííì raise ë¬¸ì´ ê·¸ ìì¸ë¥¼ ë¤ì ì¼ì¼í¬ ì ìê² í©ëë¤:
>>> try:
... raise NameError('HiThere')
... except NameError:
... print('An exception flew by!')
... raise
...
An exception flew by!
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
raise NameError('HiThere')
NameError: HiThere
8.5. ìì¸ ì°ì¶
If an unhandled exception occurs inside an except section, it will
have the exception being handled attached to it and included in the error
message:
>>> try:
... open("database.sqlite")
... except OSError:
... raise RuntimeError("unable to handle error")
...
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
open("database.sqlite")
~~~~^^^^^^^^^^^^^^^^^^^
FileNotFoundError: [Errno 2] No such file or directory: 'database.sqlite'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "<stdin>", line 4, in <module>
raise RuntimeError("unable to handle error")
RuntimeError: unable to handle error
To indicate that an exception is a direct consequence of another, the
raise statement allows an optional from clause:
# exc must be exception instance or None.
raise RuntimeError from exc
ì´ê²ì ìì¸ë¥¼ ë³íí ë ì ì©í ì ììµëë¤. ì를 ë¤ë©´:
>>> def func():
... raise ConnectionError
...
>>> try:
... func()
... except ConnectionError as exc:
... raise RuntimeError('Failed to open database') from exc
...
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
func()
~~~~^^
File "<stdin>", line 2, in func
ConnectionError
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "<stdin>", line 4, in <module>
raise RuntimeError('Failed to open database') from exc
RuntimeError: Failed to open database
It also allows disabling automatic exception chaining using the from None
idiom:
>>> try:
... open('database.sqlite')
... except OSError:
... raise RuntimeError from None
...
Traceback (most recent call last):
File "<stdin>", line 4, in <module>
raise RuntimeError from None
RuntimeError
ì°ì ë©ì»¤ëì¦ì ëí ìì¸í ë´ì©ì, ë´ì¥ ìì¸ë¥¼ 참조íììì¤.
8.6. ì¬ì©ì ì ì ìì¸Â¶
ì ìì¸ í´ëì¤ë¥¼ ë§ë¦ì¼ë¡ì¨ íë¡ê·¸ë¨ì ìì ì ìì¸ì ì´ë¦ì ë¶ì¼ ì ììµëë¤ (íì´ì¬ í´ëì¤ì ëí ìì¸í ë´ì©ì í´ëì¤ ë¥¼ ë³´ì¸ì). ìì¸ë ë³´íµ ì§ì ì ì¼ë¡ë ê°ì ì ì¼ë¡ Exception í´ëì¤ë¥¼ ê³ì¹í©ëë¤.
ìì¸ í´ëì¤ë ë¤ë¥¸ í´ëì¤ë¤ì´ í ì ìë ì´ë¤ ê²ë ê°ë¥íëë¡ ì ìë ì ìì§ë§, ë³´íµì ê°ë¨íê² ì ì§í©ëë¤. ì¢ ì¢ ìì¸ ì²ë¦¬ê¸°ê° ìë¬ì ê´í ì 보를 ì¶ì¶í ì ìëë¡ í기 ìí ëª ê°ì§ ì´í¸ë¦¬ë·°í¸ë¤ì ì ê³µíê¸°ë§ í©ëë¤.
ëë¶ë¶ì ìì¸ë íì¤ ìì¸ë¤ì ì´ë¦ë¤ê³¼ ì ì¬íê², âErrorâ ë¡ ëëë ì´ë¦ì¼ë¡ ì ìë©ëë¤.
ë§ì íì¤ ëª¨ëë¤ì ê·¸ë¤ì´ ì ìíë í¨ìë¤ìì ë°ìí ì ìë ê·¸ ìì ë§ì ìì¸ë¤ì ì ìí©ëë¤.
8.7. ë·ì 리 ëì ì ìí기¶
try 문ì ë ë¤ë¥¸ ì íì ì ì ê°ì§ ì ìëë° ëª¨ë ìí©ì ì¤íëì´ì¼ë§ íë ë·ì 리 ëìì ì ìíë ë° ì¬ì©ë©ëë¤. ì를 ë¤ì´:
>>> try:
... raise KeyboardInterrupt
... finally:
... print('Goodbye, world!')
...
Goodbye, world!
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
raise KeyboardInterrupt
KeyboardInterrupt
finally ì ì´ ìì¼ë©´, try ë¬¸ì´ ìë£ë기 ì ì finally ì ì´ ë§ì§ë§ ìì
ì¼ë¡ ì¤íë©ëë¤. finally ì ì try ë¬¸ì´ ìì¸ë¥¼ ìì±íëì§ì ê´ê³ìì´ ì¤íë©ëë¤. ë¤ìì ìì¸ê° ë°ìí ë ë ë³µì¡í ê²½ì°ë¥¼ ì¤ëª
í©ëë¤:
tryì ì ì¤ííë ëì ìì¸ê° ë°ìíë©´,exceptì ìì ìì¸ë¥¼ ì²ë¦¬í ì ììµëë¤. ìì¸ê°exceptì ìì ì²ë¦¬ëì§ ìì¼ë©´,finallyì ì´ ì¤íë í ìì¸ê° ë¤ì ë°ìí©ëë¤.exceptëelseì ì¤í ì¤ì ìì¸ê° ë°ìí ì ììµëë¤. ë¤ì,finallyì ì´ ì¤íë í ìì¸ê° ë¤ì ë°ìí©ëë¤.If the
finallyclause executes abreak,continueorreturnstatement, exceptions are not re-raised. This can be confusing and is therefore discouraged. From version 3.14 the compiler emits aSyntaxWarningfor it (see PEP 765).try문ì´break,continueëëreturn문ì ëë¬íë©´,finallyì ìbreak,continueëëreturn문 ì¤í ì§ì ì ì¤íë©ëë¤.If a
finallyclause includes areturnstatement, the returned value will be the one from thefinallyclauseâsreturnstatement, not the value from thetryclauseâsreturnstatement. This can be confusing and is therefore discouraged. From version 3.14 the compiler emits aSyntaxWarningfor it (see PEP 765).
ì를 ë¤ë©´:
>>> def bool_return():
... try:
... return True
... finally:
... return False
...
>>> bool_return()
False
ë ë³µì¡í ì:
>>> def divide(x, y):
... try:
... result = x / y
... except ZeroDivisionError:
... print("division by zero!")
... else:
... print("result is", result)
... finally:
... print("executing finally clause")
...
>>> divide(2, 1)
result is 2.0
executing finally clause
>>> divide(2, 0)
division by zero!
executing finally clause
>>> divide("2", "1")
executing finally clause
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
divide("2", "1")
~~~~~~^^^^^^^^^^
File "<stdin>", line 3, in divide
result = x / y
~~^~~
TypeError: unsupported operand type(s) for /: 'str' and 'str'
ë³´ì¸ ë°ì ê°ì´, finally ì ì 모ë ê²½ì°ì ì¤íë©ëë¤. ë 문ìì´ì ëë ì ë°ìí TypeError ë except ì ì ìí´ ì²ë¦¬ëì§ ìê³ finally ì ì´ ì¤íë íì ë¤ì ì¼ì´ë©ëë¤.
ì¤ì ì¸ìì ìì© íë¡ê·¸ë¨ìì, finally ì ì ì¸ë¶ ììì ì¬ì©í ë, ì±ê³µì ì¸ì§ ìëì§ì ê´ê³ìì´, ê·¸ ììì ë°ë©íë ë° ì ì©í©ëë¤ (íì¼ì´ë ë¤í¸ìí¬ ì°ê²° ê°ì ê²ë¤).
8.8. 미리 ì ìë ë·ì 리 ëìë¤Â¶
ì´ë¤ ê°ì²´ë¤ì ê°ì²´ê° ë íì ìì ë ê°ì íë íì¤ ë·ì 리 ëìì ì ìí©ëë¤. ê·¸ ê°ì²´ë¥¼ ì¬ì©íë ì°ì°ì ì±ê³µ ì¬ë¶ì ê´ê³ììµëë¤. íì¼ì ì´ê³ ê·¸ ë´ì©ì íë©´ì ì¸ìíë ¤ê³ íë ë¤ì ì를 ë³´ì¸ì.
for line in open("myfile.txt"):
print(line, end="")
ì´ ì½ëì 문ì ì ì ì´ ë¶ë¶ì´ ì¤íì ëë¸ ë¤ìë ì측í ì ìë ê¸°ê° ëì íì¼ì ì´ë¦° ì±ë¡ ëë¤ë ê²ì
ëë¤. ê°ë¨í ì¤í¬ë¦½í¸ììë 문ì ê° ëì§ ìì§ë§, í° ìì© íë¡ê·¸ë¨ììë 문ì ê° ë ì ììµëë¤. with 문ì íì¼ê³¼ ê°ì ê°ì²´ë¤ì´ ì¦ì ì¬ë°ë¥´ê² ë·ì 리 ëëë¡ ë³´ì¥íë ë°©ë²ì ì ê³µí©ëë¤.
with open("myfile.txt") as f:
for line in f:
print(line, end="")
문ì¥ì´ ì¤íë íì, ì¤ì ì²ë¦¬íë ë° ë¬¸ì ê° ë°ìíëë¼ë, íì¼ f ë íì ë«íëë¤. íì¼ê³¼ ê°ì´, 미리 ì ìë ë·ì 리 ëìë¤ì ì ê³µíë ê°ì²´ë¤ì ê·¸ë¤ì ì¤ëª ììì ì´ ì¬ì¤ì ì¤ëª í©ëë¤.
8.10. Enriching Exceptions with Notes¶
When an exception is created in order to be raised, it is usually initialized
with information that describes the error that has occurred. There are cases
where it is useful to add information after the exception was caught. For this
purpose, exceptions have a method add_note(note) that accepts a string and
adds it to the exceptionâs notes list. The standard traceback rendering
includes all notes, in the order they were added, after the exception.
>>> try:
... raise TypeError('bad type')
... except Exception as e:
... e.add_note('Add some information')
... e.add_note('Add some more information')
... raise
...
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
raise TypeError('bad type')
TypeError: bad type
Add some information
Add some more information
>>>
For example, when collecting exceptions into an exception group, we may want to add context information for the individual errors. In the following each exception in the group has a note indicating when this error has occurred.
>>> def f():
... raise OSError('operation failed')
...
>>> excs = []
>>> for i in range(3):
... try:
... f()
... except Exception as e:
... e.add_note(f'Happened in Iteration {i+1}')
... excs.append(e)
...
>>> raise ExceptionGroup('We have some problems', excs)
+ Exception Group Traceback (most recent call last):
| File "<stdin>", line 1, in <module>
| raise ExceptionGroup('We have some problems', excs)
| ExceptionGroup: We have some problems (3 sub-exceptions)
+-+---------------- 1 ----------------
| Traceback (most recent call last):
| File "<stdin>", line 3, in <module>
| f()
| ~^^
| File "<stdin>", line 2, in f
| raise OSError('operation failed')
| OSError: operation failed
| Happened in Iteration 1
+---------------- 2 ----------------
| Traceback (most recent call last):
| File "<stdin>", line 3, in <module>
| f()
| ~^^
| File "<stdin>", line 2, in f
| raise OSError('operation failed')
| OSError: operation failed
| Happened in Iteration 2
+---------------- 3 ----------------
| Traceback (most recent call last):
| File "<stdin>", line 3, in <module>
| f()
| ~^^
| File "<stdin>", line 2, in f
| raise OSError('operation failed')
| OSError: operation failed
| Happened in Iteration 3
+------------------------------------
>>>