You are here: Home > Dive Into Python > Exceptions and File Handling > Working with File Objects | << >> | ||||
Dive Into PythonPython from novice to pro |
Python has a built-in function, open, for opening a file on disk. open returns a file object, which has methods and attributes for getting information about and manipulating the opened file.
>>> f = open("/music/_singles/kairo.mp3", "rb") >>> f <open file '/music/_singles/kairo.mp3', mode 'rb' at 010E3988> >>> f.mode 'rb' >>> f.name '/music/_singles/kairo.mp3'
The open method can take up to three parameters: a filename, a mode, and a buffering parameter. Only the first one, the filename, is required; the other two are optional. If not specified, the file is opened for reading in text mode. Here you are opening the file for reading in binary mode. (print open.__doc__ displays a great explanation of all the possible modes.) | |
The open function returns an object (by now, this should not surprise you). A file object has several useful attributes. | |
The mode attribute of a file object tells you in which mode the file was opened. | |
The name attribute of a file object tells you the name of the file that the file object has open. |
After you open a file, the first thing you'll want to do is read from it, as shown in the next example.
>>> f <open file '/music/_singles/kairo.mp3', mode 'rb' at 010E3988> >>> f.tell() 0 >>> f.seek(-128, 2) >>> f.tell() 7542909 >>> tagData = f.read(128) >>> tagData 'TAGKAIRO****THE BEST GOA ***DJ MARY-JANE*** Rave Mix 2000http://mp3.com/DJMARYJANE \037' >>> f.tell() 7543037
Open files consume system resources, and depending on the file mode, other programs may not be able to access them. It's important to close files as soon as you're finished with them.
>>> f <open file '/music/_singles/kairo.mp3', mode 'rb' at 010E3988> >>> f.closed False >>> f.close() >>> f <closed file '/music/_singles/kairo.mp3', mode 'rb' at 010E3988> >>> f.closed True >>> f.seek(0) Traceback (innermost last): File "<interactive input>", line 1, in ? ValueError: I/O operation on closed file >>> f.tell() Traceback (innermost last): File "<interactive input>", line 1, in ? ValueError: I/O operation on closed file >>> f.read() Traceback (innermost last): File "<interactive input>", line 1, in ? ValueError: I/O operation on closed file >>> f.close()
The closed attribute of a file object indicates whether the object has a file open or not. In this case, the file is still open (closed is False). | |
To close a file, call the close method of the file object. This frees the lock (if any) that you were holding on the file, flushes buffered writes (if any) that the system hadn't gotten around to actually writing yet, and releases the system resources. | |
The closed attribute confirms that the file is closed. | |
Just because a file is closed doesn't mean that the file object ceases to exist. The variable f will continue to exist until it goes out of scope or gets manually deleted. However, none of the methods that manipulate an open file will work once the file has been closed; they all raise an exception. | |
Calling close on a file object whose file is already closed does not raise an exception; it fails silently. |
Now you've seen enough to understand the file handling code in the fileinfo.py sample code from the previous chapter. This example shows how to safely open and read from a file and gracefully handle errors.
try: fsock = open(filename, "rb", 0) try: fsock.seek(-128, 2) tagdata = fsock.read(128) finally: fsock.close() . . . except IOError: pass
Because opening and reading files is risky and may raise an exception, all of this code is wrapped in a try...except block. (Hey, isn't standardized indentation great? This is where you start to appreciate it.) | |
The open function may raise an IOError. (Maybe the file doesn't exist.) | |
The seek method may raise an IOError. (Maybe the file is smaller than 128 bytes.) | |
The read method may raise an IOError. (Maybe the disk has a bad sector, or it's on a network drive and the network just went down.) | |
This is new: a try...finally block. Once the file has been opened successfully by the open function, you want to make absolutely sure that you close it, even if an exception is raised by the seek or read methods. That's what a try...finally block is for: code in the finally block will always be executed, even if something in the try block raises an exception. Think of it as code that gets executed on the way out, regardless of what happened before. | |
At last, you handle your IOError exception. This could be the IOError exception raised by the call to open, seek, or read. Here, you really don't care, because all you're going to do is ignore it silently and continue. (Remember, pass is a Python statement that does nothing.) That's perfectly legal; “handling” an exception can mean explicitly doing nothing. It still counts as handled, and processing will continue normally on the next line of code after the try...except block. |
As you would expect, you can also write to files in much the same way that you read from them. There are two basic file modes:
Either mode will create the file automatically if it doesn't already exist, so there's never a need for any sort of fiddly "if the log file doesn't exist yet, create a new empty file just so you can open it for the first time" logic. Just open it and start writing.
>>> logfile = open('test.log', 'w') >>> logfile.write('test succeeded') >>> logfile.close() >>> print file('test.log').read() test succeeded >>> logfile = open('test.log', 'a') >>> logfile.write('line 2') >>> logfile.close() >>> print file('test.log').read() test succeededline 2
<< Exceptions and File Handling |
| 1 | 2 | 3 | 4 | 5 | 6 | 7 | |
Iterating with for Loops >> |