[Python] Exception Handling Technology (2)

Source: Internet
Author: User
Tags finally block

[Python] Exception Handling Technology (2)


Re-raising Exceptions

In some cases, clearing jobs requires different error handling and correct handling. For example, if a database operation error occurs, you need to roll back the transaction, but there is no error, You need to perform the commit operation. In this case, you must capture an exception and process it. An intermediate layer exception needs to be captured and removed before some operations are executed, and then the error handling process is further propagated to the upper layer.

#!/usr/bin/env python"""Illustrate database transaction management using sqlite3."""import loggingimport osimport sqlite3import sysDB_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))    returndef 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()    returndef 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 0if __name__ == '__main__':    sys.exit(main())

In this case, a separate exception handling is used in do_database_work () to cancel the previous database operation, and the global exception processor prints an error message.

$ python sqlite_error.pyINFO:db_example:Creating tablesINFO: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 transactionERROR:db_example:Error while doing database workTraceback (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

Keep Error Tracking Information Preserving Tracebacks

Many times in your program, cleaning the program itself causes other exceptions. This usually happens when the system resources (memory, hard disk resources, etc.) are insufficient. Exceptions caused by exception handling may overwrite the original fundamental exceptions, if they are not handled.

#!/usr/bin/env pythonimport sysimport tracebackdef throws():    raise RuntimeError('error from throws')def nested():    try:        throws()    except:        cleanup()        raisedef cleanup():    raise RuntimeError('error from cleanup')def main():    try:        nested()        return 0    except Exception, err:        traceback.print_exc()        return 1if __name__ == '__main__':    sys.exit(main())

When the cleanup () method causes an exception when processing the original error, the exception handling mechanism will reset to handle the new error. (So we can only see the exception in the exception, and the exception is lost)

$ python masking_exceptions.pyTraceback (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

Even if the second exception is caught, the original exception cannot be saved.

#!/usr/bin/env pythonimport sysimport tracebackdef 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 errordef cleanup():    raise RuntimeError('error from cleanup')def main():    try:        nested()        return 0    except Exception, err:        traceback.print_exc()        return 1if __name__ == '__main__':    sys.exit(main())
Here, even if we encapsulate cleanup () calls in an exception handling block that ignores exceptions, the errors caused by cleanup () will overwrite the original errors, because only one exception is saved in the context.

$ python masking_exceptions_catch.pyTraceback (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
One very naive way is to catch the original exception, save it in a variable, and then explicitly cause this exception again.

#!/usr/bin/env pythonimport sysimport tracebackdef throws():    raise RuntimeError('error from throws')def nested():    try:        throws()    except Exception, original_error:        try:            cleanup()        except:            pass # ignore errors in cleanup        raise original_errordef cleanup():    raise RuntimeError('error from cleanup')def main():    try:        nested()        return 0    except Exception, err:        traceback.print_exc()        return 1if __name__ == '__main__':    sys.exit(main())

As you can see, this method cannot save all error traces. Stack tracing does not print the throws () method at all. Although the print is the original error.
$ Python Merge (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_errorRuntimeError: error from throws ''' a better way is to first re-cause the original exception and then clear it in try: finally block. '''#! /Usr/bin/env pythonimport sysimport tracebackdef throws (): raise RuntimeError ('error from throws ') def nested (): try: throws () handle T Exception, original_error: try: raise finally: try: cleanup () failed T: pass # ignore errors in cleanupdef cleanup (): raise RuntimeError ('error from cleanup') def main (): try: nested () return 0 failed t Exception, err: traceback. print_exc () return 1if _ name _ = '_ main _': sys. exit (main ())

This structure prevents original exceptions from being overwritten by subsequent exceptions and saves all error information to the Error Tracking stack.

$ python masking_exceptions_finally.pyTraceback (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
This special indent may not look good, But It outputs all the information you want. The original error information is printed out, including all error traces.



Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.