When you want to write a program that opens and reads a file, that program needs to tell Python where that file is. By default, Python assumes that the file you want to read is in the same directory as the program that is doing the reading. If you’re working in IDLE as you read this book, there’s a little setup you should do:
Make a directory, perhaps called file_examples.
In IDLE, select File→New Window and type (or copy and paste) the following:
| | First line of text |
| | Second line of text |
| | Third line of text |
Save this file in your file_examples directory under the name file_example.txt.
In IDLE, select File→New Window and type (or copy and paste) this program:
| | infile = open('file_example.txt', 'r') |
| | contents = infile.read() |
| | infile.close() |
| | print(contents) |
Save this as file_reader.py in your file_examples directory.
When you run this program, this is what gets printed:
| | First line of text |
| | Second line of text |
| | Third line of text |
You must save the two files in the same directory, as you’ll see in the next section. Additionally, this approach will not work if you attempt to use the same commands from the Python shell.
The built-in function open opens a file (much like opening a book when you want to read it) and returns an object that knows how to retrieve information from the file, stored in the variable infile. This object also keeps track of how much you’ve read and which part of the file you’re about to read next. The marker that keeps track of the current location in the file is called the current [file] position (also known as the file cursor) and acts much like a bookmark. The current position is initially set at the beginning of the file, but as you read or write data, it moves to the end of the data that you have just read or written.
Files can be read, written to, and added to
The first argument in the example call to the function open('file_example.txt', 'r') is the name of the file to open, and the second argument, ’r’, indicates that you want to read the file; it is referred to as the file mode. Other options for the mode include ’w’ for writing and ’a’ for appending, which you’ll see later in this chapter. If you call open with only the name of the file (omitting the mode), then the default is ’r’.
The second statement, contents = infile.read(), tells Python that you want to read the contents of the entire file into a string, which you assign to a variable called contents, and the third statement, infile.close, releases all resources associated with the open file object.
The last statement prints the string.
When you run the program, you’ll see that newline characters are treated just like every other character; it’s just another character in the file.
Working with a file is a special case of a general programming pattern known as the Acquire--Use--Release pattern: obtain access to a resource, perform an action with the resource, and then clean up and release the resource. In the previous file example, you gained access to a file by calling the open function, then read the file contents, and finally tidied up by closing the file.
There’s a catch: if a problem occurs and an error arises, your code may fail to execute the statement infile.close, and the associated resources are never released. Python provides a with statement for situations like this, where you always want to tidy up, regardless of whether an error occurs. For this reason, the with statement is frequently used for file access.
Here is the same example using a with statement:
| | with open('file_example.txt', 'r') as infile: |
| | contents = infile.read() |
| | |
| | print(contents) |
The general form of a with statement is as follows:
| | with expression as variable: |
| | block |
A file path specifies the location of a file or folder in your computer’s file system. It consists of a sequence of directory names leading from the root directory (or another starting point) to the target location, and it may optionally end with a file name.
Here is an example of the file path for file_example.txt:
/Users/pgries/Desktop/file_examples/file_example.txt
This file path is on a computer running Apple OS X. A file path in Linux would look similar. Both operating systems use a forward slash as the directory separator.
In Microsoft Windows, the path usually begins with a drive letter, such as C:. There is one drive letter per disk. Also, Microsoft Windows uses a backslash as the directory separator. (Before working with backslashes as directory separators, consider reviewing .)
Here is a path in Windows:
C:\Users\pgries\Desktop\file_examples\file_example.txt
Python’s file-handling operations will automatically translate forward slashes to work in Windows, if needed, much like these operations automatically translate the two kinds of newlines that you learned about in .
Python maintains the current working directory, which is the directory it uses to locate files and folders. When you run a Python program, the current working directory is the directory where that program is started. For example, this may be the path of the file you have open in IDLE:
/home/pgries/Documents/py4book/Book/code/fileproc/program.py
Then this is the current working directory:
/home/pgries/Documents/py4book/Book/code/fileproc
When you call the open function, it searches for the specified file in the current working directory.
The default current working directory for the Python shell varies depending on the operating system. You can find out the current working directory using the getcwd function from the os module:
| | >>> import os |
| | >>> os.getcwd() |
| | '/home/pgries' |
To open a file in a different directory, you must specify its location. You can do that with an absolute path or with a relative path. An absolute path (like all the previous examples) starts at the root of the file system, and a relative path is relative to the current working directory. Alternatively, you can change Python’s current working directory to a different directory using the function chdir, short for “change directory”:
| | >>> os.chdir('/home/pgries/Documents/py3book') |
| | >>> os.getcwd() |
| | '/home/pgries/Documents/py3book' |
Let’s say that you have a program called reader.py and a directory called data in the same directory as reader.py. Inside data, you might have files called data1.txt and data2.txt. Here is how you would open data1.txt:
| | open('data/data1.txt', 'r') |
The string ’data/data1.txt’ is a relative path.
To look in the parent directory (the directory above the current working directory), use two dots:
| | open('../data1.txt', 'r') |
You can chain the dots to go up multiple directories. Here, Python looks for data1.txt three directories above the current working directory and then down into a data directory:
| | open('../../../data/data1.txt', 'r') |
If you’re still not clear on how directory paths work, try looking at this discussion on Wikipedia.