In this section, we’ll write a simple text file that might be used by an accounts-receivable system to track the money owed by a company’s clients. We’ll then read that text file to confirm that it contains the data. For each client, we’ll store the client’s account number, last name and account balance owed to the company. Together, these data fields represent a client record. Python imposes no structure on a file, so notions such as records do not exist natively in Python. Programmers must structure files to meet their applications’ requirements. We’ll create and maintain this file in order by account number. In this sense, the account number may be thought of as a record key. For this chapter, we assume that you launch IPython from the ch09
examples folder.
with
StatementLet’s create an accounts.txt
file and write five client records to the file. Generally, records in text files are stored one per line, so we end each record with a newline character:
In [1]: with open('accounts.txt', mode='w') as accounts:
...: accounts.write('100 Jones 24.98 ')
...: accounts.write('200 Doe 345.67 ')
...: accounts.write('300 White 0.00 ')
...: accounts.write('400 Stone -42.16 ')
...: accounts.write('500 Rich 224.62 ')
...:
You can also write to a file with print
(which automatically outputs a
), as in
print('100 Jones 24.98', file=accounts)
with
StatementMany applications acquire resources, such as files, network connections, database connections and more. You should release resources as soon as they’re no longer needed. This practice ensures that other applications can use the resources. Python’s with
statement:
acquires a resource (in this case, the file object for accounts.txt
) and assigns its corresponding object to a variable (accounts
in this example),
allows the application to use the resource via that variable, and
calls the resource object’s close
method to release the resource when program control reaches the end of the with
statement’s suite.
open
The built-in open
function opens the file accounts.txt
and associates it with a file object. The mode
argument specifies the file-open mode, indicating whether to open a file for reading from the file, for writing to the file or both. The mode 'w'
opens the file for writing, creating the file if it does not exist. If you do not specify a path to the file, Python creates it in the current folder (ch09
). Be careful—opening a file for writing deletes all the existing data in the file. By convention, the
.txt
file extension indicates a plain text file.
The with
statement assigns the object returned by open
to the variable accounts
in the as
clause. In the with
statement’s suite, we use the variable accounts
to interact with the file. In this case, we call the file object’s write
method five times to write five records to the file, each as a separate line of text ending in a newline. At the end of the with
statement’s suite, the with
statement implicitly calls the file object’s close
method to close the file.
accounts.txt
File After executing the previous snippet, your ch09
directory contains the file accounts.txt
with the following contents, which you can view by opening the file in a text editor:
100 Jones 24.98
200 Doe 345.67
300 White 0.00
400 Stone -42.16
500 Rich 224.62
In the next section, you’ll read the file and display its contents.
(Fill-In) The implicitly releases resources when its suite finishes executing.
Answer: with
.
(True/False) It’s good practice to keep resources open until your program terminates.
Answer: False. It’s good practice to close resources as soon as the program no longer needs them.
(IPython Session) Create a grades.txt
file and write to it the following three records consisting of student IDs, last names and letter grades:
1 Red A
2 Green B
3 White A
Answer:
In [1]: with open('grades.txt', mode='w') as grades:
...: grades.write('1 Red A ')
...: grades.write('2 Green B ')
...: grades.write('3 White A ')
...:
After the preceding snippet executed, we used a text editor to view the grades.txt
file:
1 Red A
2 Green B
3 White A
We just created the text file accounts.txt
and wrote data to it. Now let’s read that data from the file sequentially from beginning to end. The following session reads records from the file accounts.txt
and displays the contents of each record in columns with the Account
and Name
columns left aligned and the Balance
column right aligned, so the decimal points align vertically:
In [1]: with open('accounts.txt', mode='r') as accounts:
...: print(f'{"Account":<10}{"Name":<10}{"Balance":>10}')
...: for record in accounts:
...: account, name, balance = record.split()
...: print(f'{account:<10}{name:<10}{balance:>10}')
...:
Account Name Balance
100 Jones 24.98
200 Doe 345.67
300 White 0.00
400 Stone -42.16
500 Rich 224.62
If the contents of a file should not be modified, open the file for reading only—another example of the principle of least privilege. This prevents the program from accidentally modifying the file. You open a file for reading by passing the 'r'
file-open mode as function open
’s second argument. If you do not specify the folder in which to store the file, open
assumes the file is in the current folder.
Iterating through a file object, as shown in the preceding for
statement, reads one line at a time from the file and returns it as a string. For each record
(that is, line) in the file, string method split
returns tokens in the line as a list, which we unpack into the variables account
, name
and balance
.1 The last statement in the for
statement’s suite displays these variables in columns using field widths.
readlines
The file object’s readlines
method also can be used to read an entire text file. The method returns each line as a string in a list of strings. For small files, this works well, but iterating over the lines in a file object, as shown above, can be more efficient.2 Calling readlines
for a large file can be a time-consuming operation, which must complete before you can begin using the list of strings. Using the file object in a for
statement enables your program to process each text line as it’s read.
While reading through a file, the system maintains a file-position pointer representing the location of the next character to read. Sometimes it’s necessary to process a file sequentially from the beginning several times during a program’s execution. Each time, you must reposition the file-position pointer to the beginning of the file, which you can do either by closing and reopening the file, or by calling the file object’s seek
method, as in
file_object.seek(0)
The latter approach is faster.
(Fill-In) A file object’s method can be used to reposition the file-position pointer.
Answer: seek
.
(True/False) By default, iterating through a file object with a for
statement reads one line at a time from the file and returns it as a string.
Answer: True.
(IPython Session) Read the file grades.txt
that you created in the previous section’s Self Check and display it in columns with the column heads 'ID'
, 'Name'
and 'Grade'
.
Answer:
In [1]: with open('grades.txt', 'r') as grades:
...: print(f'{"ID":<4}{"Name":<7}{"Grade"}')
...: for record in grades:
...: student_id, name, grade = record.split()
...: print(f'{student_id:<4}{name:<7}{grade}')
...:
ID Name Grade
1 Red A
2 Green B
3 White A
18.224.59.192