有的时候清除工作需要对错误处理和正确处理是不同的。例如,数据库操作错误需要回滚事务,但是没有错误需要commit操作。这种情况下,你必须要捕获异常并且处理它。中间的层异常 需要被捕获取消之前执行的部分操作,然后继续传播给上层的错误处理。
#!/usr/bin/env python
"""Illustrate database transaction management using sqlite3.
"""
import logging
import os
import sqlite3
import sys
DB_NAME = ‘mydb.sqlite‘
logging.basicConfig(level=logging.INFO)
log = logging.getLogger(‘db_example‘)
def throws():
    raise RuntimeError(‘this is the error message‘)
def create_tables(cursor):
    log.info(‘Creating tables‘)
    cursor.execute("create table module (name text, description text)")
def insert_data(cursor):
    for module, description in [(‘logging‘, ‘error reporting and auditing‘),
                                (‘os‘, ‘Operating system services‘),
                                (‘sqlite3‘, ‘SQLite database access‘),
                                (‘sys‘, ‘Runtime services‘),
                                ]:
        log.info(‘Inserting %s (%s)‘, module, description)
        cursor.execute("insert into module values (?, ?)", (module, description))
    return
def do_database_work(do_create):
    db = sqlite3.connect(DB_NAME)
    try:
        cursor = db.cursor()
        if do_create:
            create_tables(cursor)
        insert_data(cursor)
        throws()
    except:
        db.rollback()
        log.error(‘Rolling back transaction‘)
        raise
    else:
        log.info(‘Committing transaction‘)
        db.commit()
    return
def main():
    do_create = not os.path.exists(DB_NAME)
    try:
        do_database_work(do_create)
    except Exception, err:
        log.exception(‘Error while doing database work‘)
        return 1
    else:
        return 0
if __name__ == ‘__main__‘:
    sys.exit(main())$ python sqlite_error.py
INFO:db_example:Creating tables
INFO:db_example:Inserting logging (error reporting and auditing)
INFO:db_example:Inserting os (Operating system services)
INFO:db_example:Inserting sqlite3 (SQLite database access)
INFO:db_example:Inserting sys (Runtime services)
ERROR:db_example:Rolling back transaction
ERROR:db_example:Error while doing database work
Traceback (most recent call last):
  File "sqlite_error.py", line 51, in main
    do_database_work(do_create)
  File "sqlite_error.py", line 38, in do_database_work
    throws()
  File "sqlite_error.py", line 15, in throws
    raise RuntimeError(‘this is the error message‘)
RuntimeError: this is the error message很多时候在你的程序中,异常中清理程序自己又引起了其他的异常。这种情况一般是发生在系统资源(内存,硬盘资源等..)不足的时候。在异常处理中引起的异常可能会覆盖了原先根本的异常,如果没有对这些异常中的异常没有被处理。
#!/usr/bin/env python
import sys
import traceback
def throws():
    raise RuntimeError(‘error from throws‘)
def nested():
    try:
        throws()
    except:
        cleanup()
        raise
def cleanup():
    raise RuntimeError(‘error from cleanup‘)
def main():
    try:
        nested()
        return 0
    except Exception, err:
        traceback.print_exc()
        return 1
if __name__ == ‘__main__‘:
    sys.exit(main())$ python masking_exceptions.py
Traceback (most recent call last):
  File "masking_exceptions.py", line 21, in main
    nested()
  File "masking_exceptions.py", line 13, in nested
    cleanup()
  File "masking_exceptions.py", line 17, in cleanup
    raise RuntimeError(‘error from cleanup‘)
RuntimeError: error from cleanup#!/usr/bin/env python
import sys
import traceback
def throws():
    raise RuntimeError(‘error from throws‘)
def nested():
    try:
        throws()
    except:
        try:
            cleanup()
        except:
            pass # ignore errors in cleanup
        raise # we want to re-raise the original error
def cleanup():
    raise RuntimeError(‘error from cleanup‘)
def main():
    try:
        nested()
        return 0
    except Exception, err:
        traceback.print_exc()
        return 1
if __name__ == ‘__main__‘:
    sys.exit(main())在这里,即使我们把cleanup()的调用封装在一个忽略异常的异常处理块里面,cleanup()引起的错误也会覆盖原本的错误,因为上下文中只有一个异常被保存。
$ python masking_exceptions_catch.py
Traceback (most recent call last):
  File "masking_exceptions_catch.py", line 24, in main
    nested()
  File "masking_exceptions_catch.py", line 14, in nested
    cleanup()
  File "masking_exceptions_catch.py", line 20, in cleanup
    raise RuntimeError(‘error from cleanup‘)
RuntimeError: error from cleanup一种非常幼稚的做法是捕获原本的异常,保存在一个变量中,然后明确的再次引起这个异常。
#!/usr/bin/env python
import sys
import traceback
def throws():
    raise RuntimeError(‘error from throws‘)
def nested():
    try:
        throws()
    except Exception, original_error:
        try:
            cleanup()
        except:
            pass # ignore errors in cleanup
        raise original_error
def cleanup():
    raise RuntimeError(‘error from cleanup‘)
def main():
    try:
        nested()
        return 0
    except Exception, err:
        traceback.print_exc()
        return 1
if __name__ == ‘__main__‘:
    sys.exit(main())$ python masking_exceptions_reraise.py
Traceback (most recent call last):
  File "masking_exceptions_reraise.py", line 24, in main
    nested()
  File "masking_exceptions_reraise.py", line 17, in nested
    raise original_error
RuntimeError: error from throws
’‘’
更好的做法是先重新引起一个原始的异常,然后在try:finally块中进行清除。
‘’‘
#!/usr/bin/env python
import sys
import traceback
def throws():
    raise RuntimeError(‘error from throws‘)
def nested():
    try:
        throws()
    except Exception, original_error:
        try:
            raise
        finally:
            try:
                cleanup()
            except:
                pass # ignore errors in cleanup
def cleanup():
    raise RuntimeError(‘error from cleanup‘)
def main():
    try:
        nested()
        return 0
    except Exception, err:
        traceback.print_exc()
        return 1
if __name__ == ‘__main__‘:
    sys.exit(main())$ python masking_exceptions_finally.py
Traceback (most recent call last):
  File "masking_exceptions_finally.py", line 26, in main
    nested()
  File "masking_exceptions_finally.py", line 11, in nested
    throws()
  File "masking_exceptions_finally.py", line 7, in throws
    raise RuntimeError(‘error from throws‘)
RuntimeError: error from throws这种特别的缩进可能不是很好看,但是输出了所有想要的信息。原始的错误信息被打印出来了,其中也包括了所有的错误跟踪。
[Python]异常处理技术(二),布布扣,bubuko.com
原文:http://blog.csdn.net/orangleliu/article/details/22417245