|You are here: Home > Dive Into Python > Exceptions and File Handling||<< >>|
Python from novice to pro
- 6.1. Handling Exceptions
- 6.2. Working with File Objects
- 6.3. Iterating with for Loops
- 6.4. Using sys.modules
- 6.5. Working with Directories
- 6.6. Putting It All Together
- 6.7. Summary
In this chapter, you will dive into exceptions, file objects, for loops, and the os and sys modules. If you've used exceptions in another programming language, you can skim the first section to get a sense of Python's syntax. Be sure to tune in again for file handling.
Like many other programming languages, Python has exception handling via try...except blocks.
|Python uses try...except to handle exceptions and raise to generate them. Java and C++ use try...catch to handle exceptions, and throw to generate them.|
Exceptions are everywhere in Python. Virtually every module in the standard Python library uses them, and Python itself will raise them in a lot of different circumstances. You've already seen them repeatedly throughout this book.
- Accessing a non-existent dictionary key will raise a KeyError exception.
- Searching a list for a non-existent value will raise a ValueError exception.
- Calling a non-existent method will raise an AttributeError exception.
- Referencing a non-existent variable will raise a NameError exception.
- Mixing datatypes without coercion will raise a TypeError exception.
In each of these cases, you were simply playing around in the Python IDE: an error occurred, the exception was printed (depending on your IDE, perhaps in an intentionally jarring shade of red), and that was that. This is called an unhandled exception. When the exception was raised, there was no code to explicitly notice it and deal with it, so it bubbled its way back to the default behavior built in to Python, which is to spit out some debugging information and give up. In the IDE, that's no big deal, but if that happened while your actual Python program was running, the entire program would come to a screeching halt.
An exception doesn't need result in a complete program crash, though. Exceptions, when raised, can be handled. Sometimes an exception is really because you have a bug in your code (like accessing a variable that doesn't exist), but many times, an exception is something you can anticipate. If you're opening a file, it might not exist. If you're connecting to a database, it might be unavailable, or you might not have the correct security credentials to access it. If you know a line of code may raise an exception, you should handle the exception using a try...except block.
Example 6.1. Opening a Non-Existent File
>>> fsock = open("/notthere", "r") Traceback (innermost last): File "<interactive input>", line 1, in ? IOError: [Errno 2] No such file or directory: '/notthere' >>> try: ... fsock = open("/notthere") ... except IOError: ... print "The file does not exist, exiting gracefully" ... print "This line will always print" The file does not exist, exiting gracefully This line will always print
Exceptions may seem unfriendly (after all, if you don't catch the exception, your entire program will crash), but consider the alternative. Would you rather get back an unusable file object to a non-existent file? You'd need to check its validity somehow anyway, and if you forgot, somewhere down the line, your program would give you strange errors somewhere down the line that you would need to trace back to the source. I'm sure you've experienced this, and you know it's not fun. With exceptions, errors occur immediately, and you can handle them in a standard way at the source of the problem.
There are a lot of other uses for exceptions besides handling actual error conditions. A common use in the standard Python library is to try to import a module, and then check whether it worked. Importing a module that does not exist will raise an ImportError exception. You can use this to define multiple levels of functionality based on which modules are available at run-time, or to support multiple platforms (where platform-specific code is separated into different modules).
You can also define your own exceptions by creating a class that inherits from the built-in Exception class, and then raise your exceptions with the raise command. See the further reading section if you're interested in doing this.
The next example demonstrates how to use an exception to support platform-specific functionality. This code comes from the getpass module, a wrapper module for getting a password from the user. Getting a password is accomplished differently on UNIX, Windows, and Mac OS platforms, but this code encapsulates all of those differences.
Example 6.2. Supporting Platform-Specific Functionality
# Bind the name getpass to the appropriate function try: import termios, TERMIOS except ImportError: try: import msvcrt except ImportError: try: from EasyDialogs import AskPassword except ImportError: getpass = default_getpass else: getpass = AskPassword else: getpass = win_getpass else: getpass = unix_getpass
Further Reading on Exception Handling
- Python Tutorial discusses defining and raising your own exceptions, and handling multiple exceptions at once.
- Python Library Reference summarizes all the built-in exceptions.
- Python Library Reference documents the getpass module.
- Python Library Reference documents the traceback module, which provides low-level access to exception attributes after an exception is raised.
- Python Reference Manual discusses the inner workings of the try...except block.
| 1 | 2 | 3 | 4 | 5 | 6 | 7 |
Working with File Objects >>