Learning Python

Chapter 34: Exception Coding Det

2021-06-21  本文已影响0人  枇杷膏_a56b

The try/except/else Statement

# try/except/else
try:
    print('doing sth')
except name1:
    print('doing sth')
except (name1, name2):
    print('doing sth')
except name4 as var:
    print('doing sth')
except:
    print('doing sth')
else:
    print('doing sth if no exception is raised.')

How try Statements Work


In sum, except clauses catch any matching exceptions that happen while the try block is running, and the else clause runs only if no exceptions happen while the try block runs.

Try Statement Clauses

Table 34-1. try statement clause forms

Clause form Interpretation
except: Catch all (or all other) exception types.
except name: Catch a specific exception only.
except name as value: Catch the exception and assign its instance.
except (name1, name2): Catch any of the listed exceptions.
except (name1, name2) as value: Catch the listed exception and assign its instance.
else: Run if no exceptions are raised in the try block.
finally: Always perform this block on exit.
# Exception class will catch exceptions except catching exit events.
try:
    action()
except Exception:
    ...

The try else Clause

# provides syntax in a try that makes what has happened obvious and unambiguous.
try:
    ...run code...
except IndexError:
    ...handle exception...
else:
    ...no exception occurred...

Example: default behavior:

def gobad(x, y):
    return x / y

def go_south(x):
    print(gobad(x, 0))

go_south(1) 
>>>
---------------------------------------------------------------------------
ZeroDivisionError                         Traceback (most recent call last)
<ipython-input-1-fef879750521> in <module>
      5     print(gobad(x, 0))
      6 
----> 7 go_south(1)

<ipython-input-1-fef879750521> in go_south(x)
      3 
      4 def go_south(x):
----> 5     print(gobad(x, 0))
      6 
      7 go_south(1)

<ipython-input-1-fef879750521> in gobad(x, y)
      1 def gobad(x, y):
----> 2     return x / y
      3 
      4 def go_south(x):
      5     print(gobad(x, 0))

ZeroDivisionError: division by zero

Often, this standard error message is all you need to resolve problems in your code.

Catching Built-in Exceptions

If you don't want your program terminated when Python raises an exception, simply catch it by wrapping the program logic in a try.

def kaboom(x, y):
    print(x + y)
    
try:
    kaboom([0, 1, 2], 'spam')
except TypeError:
    print('Hello World.')
print('Resuming here.') 

>>>
Hello World.
Resuming here.

The try/finally Statement

The try/finally form is useful when you want to be completely sure that an action will happen after some code runs, regardless of the exception behavior of the program. (Such as close an opened file.)

The raise Statement

raise instance # Raise instance of class (The most common)
raise class # Make and raise instance of class: make an instance
raise # Reraise the most recent exception

The following two forms are equivalent----both raise an instance of the exception class named.

raise IndexError
raise IndexError()
exc = IndexError()
raise exc

excs = [IndexError, TypeError]
raise excs[0]

Pass to the exception class constructor arguments that become available in the handler through the assigned instance.

class MyExc(Exception): pass
...
raise MyExc('spam')     # Exception class with constructor args
...
try:
    ...
except MyExc as X:     # Instance attributes available in handler.
    print(X.args)

Scopes and try except Variables

In Python 3.x, the exception reference name is not available after the block exits.

try:
    1 / 0
except Exception as X:
    print(X)

>>>
division by zero


print(X) 
>>>
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-4-5f1555447371> in <module>
----> 1 print(X)

NameError: name 'X' is not defined
X = 99
try:
    1 / 0
except Exception as X:
    print(X)

>>>
division by zero


print(X) 

>>>
print(X) 
1
print(X) 
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-6-5f1555447371> in <module>
----> 1 print(X)

NameError: name 'X' is not defined
X = 99

>>>
{'a', 'm', 'p', 's'}

print(X) 
>>>
99

Because of this, your should generally use unique variable names in your try statement's except clause.

try:
    1 / 0
except Exception as X:
    print(X)
    save_it = X

>>>
division by zero

X
>>>
NameError: name 'X' is not defined


save_it
ZeroDivisionError('division by zero')

Python 3.X Exception Chaining: raise from

raise newexception from otherexception

The assert Statement

The assert is mostly just syntactic shorthand for a common raise usage pattern.

assert test, data # The data part is optional

works like the following code:

if __debug__:
    if not test:
       raise AssertionError(data)

If the test evaluates to false, Python raises an exception: the data item (if it's provided) is used as the exception's constructor argument. Like all exceptions, the AssertionError exception will kill your program if it's not caught with a try.

Example

def f(x):
    assert x < 0, 'x must be negative'
    return x ** 2

f(1) 
>>>
---------------------------------------------------------------------------
AssertionError                            Traceback (most recent call last)
<ipython-input-12-3a4297a3995e> in <module>
      3     return x ** 2
      4 
----> 5 f(1)

<ipython-input-12-3a4297a3995e> in f(x)
      1 def f(x):
----> 2     assert x < 0, 'x must be negative'
      3     return x ** 2
      4 
      5 f(1)

AssertionError: x must be negative

with/as Context Managers

The with/as statement is designed to be an alternative to a common try/finally usage idiom.

Basic Usage

with expression [as variable]:
     with-block

The expression here is assumed to return an object that supports the context management protocol. (Usually file). It closes the file like finally.

with open(r'c:\misc\data') as myfile:
    for line in myfile:
        print(line)
        more code...
# The context management machinery guarantees that the lock is automatically acquired before the block is executed and released once the block is complete.
lock = threading.Lock()
with lock:
    ...access shared resources...
with decimal.localcontext() as ctx:
    ctx.prec = 2
    x = decimal.Decimal('1.00') / decimal.Decimal('3.00')

After this statement runs, the current thread's context manager state is automatically restored to what it was before the statement began.

The Context Management Protocol

  1. The expression is evaluated, resulting in an object known as a context manager that must have enter and exit methods.
  2. The context manager's enter method is called. The value it returns is assigned to the variable in the as clause if present, or simply discarded otherwise.
  3. No matter whether the with block raises an exception, the exit will be called. The exception, if is raised, will assign the details in the type, value, traceback in the exit. These variables will be assigned to None otherwise.

Multiple Context Managers in 3.1, 2.7, and later

...pass...

上一篇下一篇

猜你喜欢

热点阅读