Professional Documents
Culture Documents
Storing strings, lists, dictionaries, and so on in memory is fine for small amounts of data.
However, when handling large data amounts, its better to store the data in files. In this
hour, we explore using files in your Python scripts.
The various file types Python can handle are located in various places in the Raspbian
directory structure. A files type or purpose often dictates its placement within the
structure.
Figure 11.1 Linux primary subdirectories in the top root directory (/).
Each subdirectory stores particular files according to their purpose. Directory names are
written in two ways to reference these files: as an absolute directory reference or as a
relative directory reference.
An absolute directory reference always begins with the root directory. For example, when
you log in to your Raspberry Pi using the pi account, you are in the directory
/home/pi. This is an absolute directory reference because it starts with the root
directory (/).
A relative directory reference does not begin with the root directory (/). Instead, it denotes
a directory relative to where your present working directory is now. Hour 2,
Understanding the Raspbian Linux Distribution, covered that a present working
directory is where you are currently located in the directory structure. You can see the
present working directory by using the pwd shell command.
Listing 11.1 shows examples of absolute and relative directory references. In this listing,
first the pwd command shows the present working directory of the user pi. The present
working directory is currently /home/pi (which is an absolute directory reference).
Listing 11.1 Absolute and Relative Directory References
Click here to view code image
pi@raspberrypi:~$ pwd
/home/pi
pi@raspberrypi:~$ ls py3prog
sample_a.py script0402.py script0603.py script0607.py script0901.py
sample_b.py script0403.py script0604.py script0701.py script0902.py
sample.py script0601.py script0605.py script0702.py script0903.py
script0401.py script0602.py script0606.py script0703.py script0904.py
pi@raspberrypi:~$
Listing 11.2 shows a few os methods being used. The import os statement imports the
os function, and the os.mkdir method creates a new subdirectory, MyNewDir. To
switch the present working directory to the newly created subdirectory, the os.chdir
method is employed.
Listing 11.2 Using the os Function
pi@raspberrypi:~$ pwd
/home/pi
pi@raspberrypi:~$ python3
[]
>>>
>>> import os
>>> os.getcwd()
/home/pi
>>>
>>> os.mkdir(MyNewDir)
>>> os.chdir(MyNewDir)
>>> os.getcwd()
/home/pi/MyNewDir
>>>
Handling these methods within Python enables you to manage directories from within
your scripts. You can then create and use files within these directories.
Opening a File
To access a file in a Python script, use the built-in open function. The basic syntax for
using this function is as follows:
Click here to view code image
filename_variable=open(filename, options)
Several options can be used in the open function, as shown in Table 11.4.
In Listing 11.3, the open function opens a file, in write (w) mode, called
May2015TempF.txt. However, before it is opened, a few of the os functions are used
to create a directory and navigate to the files desired location.
Listing 11.3 Opening the Temperature File
Click here to view code image
pi@raspberrypi:~$ python3
[]
>>>
>>> import os
>>> os.mkdir(/home/pi/data)
>>> os.chdir(/home/pi/data)
>>> os.getcwd()
/home/pi/data
>>>
>>> temp_data_file=open(May2015TempF.txt,w)
>>>
By the Way: Possible Errors
Keep in mind if the /home/pi/data directory already exists on your system,
you might get an error message attempting Listing 11.3s os.mkdir statement.
Thats because if you attempt to create a directory using the os.mkdir method
and the directory already exists, Python is going to complain.
After the file is opened, methods on the file can be done using the variable
temp_data_file. Notice in Listing 11.3 that when the open function is used, both the
files name and the mode arguments are passed as strings. You also can use variables as
arguments, if desired.
pi@raspberrypi:~$ python3
[]
>>>
>>> import os
>>> os.chdir(/home/pi/data)
>>> os.getcwd()
/home/pi/data
>>> temp_data_file=open(May2015TempF.txt,r)
>>>
>>> temp_data_file.closed
False
>>> temp_data_file.mode
r
>>> temp_data_file.name
May2015TempF.txt
>>>
In Listing 11.4, the .closed method returns a False, indicating that the file is open.
The .mode method returns 'r', indicating the file is currently in read mode. The .name
method returns the name used in the open function. Notice that the returned filename
does not include an absolute directory reference. This is due to the files location in the
present working directorytherefore, an absolute directory reference is not needed.
In Listing 11.5, the file to be opened is not in the present working directory. Thus, a slight
change is required in the open argument.
Listing 11.5 Opening a File Using Absolute Directory Reference
Click here to view code image
pi@raspberrypi:~$ python3
[]
>>>
>>> import os
>>> os.getcwd()
/home/pi
>>> temp_data_file=open(/home/pi/data/May2015TempF.txt,r)
>>>
>>> temp_data_file.name
/home/pi/data/May2015TempF.txt
>>>
Notice in Listing 11.5 that the absolute directory reference is used for the filename in the
open function. When this is done, the file object method .name returns the entire files
name and its directory location. This is because file object method results are based on the
attributes used in the open function.
Now that you know how to open a file, you should learn how to read one. Reading files is
the next item on this hours agenda.
Reading a File
To read a file, of course, you must first use the open function to open the file. The mode
chosen within the open function must allow the file to be read, such as the r mode. After
the file is opened for reading, you can read an entire file into your Python script in one
statement, or you can read the file line-by-line.
pi@raspberrypi:~$ python3
[]
>>> temp_data_file=open(/home/pi/data/May2015TempF.txt,r)
>>>
>>> temp_data=temp_data_file.read()
>>> type(temp_data)
<class str>
>>>
>>> print(temp_data)
1 71
2 75
3 78
[]
29 84
30 84
31 67
>>> print(temp_data[0])
1
>>> print(temp_data[0:4])
1 71
>>>
In Listing 11.6, the variable temp_data receives the entire file contents from the .read
method. The data comes in as a string (str) into the temp_data variable. This is shown
using the type function. The print function and string slicing display a few chunks of
the files data (String slicing was covered in detail during Hour 10, Working with
Strings). Because all the data is stored in a single variable, desired data pieces must be
sliced from the temp_data variables string. Although this is handy, there are times you
want to read in a files data line-by-line.
pi@raspberrypi:~$ python3
[]
>>> temp_data_file=open(/home/pi/data/May2015TempF.txt,r)
>>>
>>> for the_date in range(1,31+1):
temp_data=temp_data_file.readline()
print(temp_data,end=)
1 71
2 75
3 78
[]
29 84
30 84
31 67
>>>
Notice in Listing 11.7 that when printing the temperature data, the print functions
newline (\n) is suppressed using end=''. This is needed because the data already has a
\n character on each lines end. If not suppressed, the print functions newline together
with the datas newline will cause output to be double-spaced.
Reading a file line-by-line, as you would expect, reads the file in sequential order. Python
maintains a file pointer that keeps track of its current position in a file. Using the .tell
method, the current file pointers position is shown multiple times in Listing 11.8. Notice
that the pointer position changes after each data file line is read. Also in Listing 11.8, the
.tell method displays the current file pointer position immediately after the file is
opened. Because the file was just opened, the initial file pointer is set to 0 (the files
beginning).
Listing 11.8 Following the File Pointer Using .tell
Click here to view code image
pi@raspberrypi:~$ python3
[]
>>> temp_data_file=open(/home/pi/data/May2015TempF.txt,r)
>>>
>>> temp_data_file.tell()
0
>>> for the_data in range(1,31+1):
temp_data=temp_data_file.readline()
print(temp_data,end=)
temp_data_file.tell()
1 71
5
2 75
10
3 78
15
[]
30 84
171
31 67
177
>>>
The file pointers progress is displayed in the preceding example, using a .tell method
embedded inside a for loop. Within the for loop, after each line is read and printed, the
file pointers current position is shown. Each file pointers result indicates the next
character to read.
Listing 11.9 uses the .read method on temp_data_file to read in the files first four
characters. The following .tell method indicates that the file pointer is now pointing at
character number 4. The subsequent .read grabs only one character, which is the
newline (\n) escape sequence. This is why the print command, which follows, prints
two blank lines.
Listing 11.9 Reading File Data Using .read
Click here to view code image
pi@raspberrypi:~$ python3
[]
>>> temp_data_file=open(/home/pi/data/May2015TempF.txt,r)
>>>
>>> temp_data=temp_data_file.read(4)
>>> print(temp_data)
1 71
>>>
>>> temp_data_file.tell()
4
>>> temp_data=temp_data_file.read(1)
>>> print(temp_data)
>>> temp_data_file.tell()
5
>>> temp_data=temp_data_file.read(4)
>>> print(temp_data)
2 75
>>> temp_data_file.tell()
9
>>>
To reposition the file pointer back to the files beginning, the .seek method can be used.
The .seek method has the following basic syntax:
Click here to view code image
filename_variable.seek(position number)
The position number for the files start is 0. Listing 11.10 shows an example of
using .seek and .read to read a file in a nonsequential manner.
Listing 11.10 Repositioning the File Pointer Using .seek
Click here to view code image
>>>
>>> temp_data_file.tell()
9
>>> temp_data_file.seek(0)
0
>>> temp_data=temp_data_file.read(4)
>>> print(temp_data)
1 71
>>> temp_data_file.seek(25)
25
>>> temp_data=temp_data_file.read(4)
>>> print(temp_data)
6 86
>>>
Notice in Listing 11.10 that after the file pointer is set to position 0 using .seek, the
.read method reads the files next four characters. This is similar to how the
.readline method works in Listing 11.7. However, because only four characters are
read each time in this example, the newline (\n) does not need to be suppressed in the
print functions.
In the preceding example, when the file pointer is positioned at character 25 using
.seek, the next .read method again reads the next four characters, starting at that
position. In effect, this skips several of the files data lines. Thus, using the .seek and
.read methods together enables you to read a file in a nonsequential manner.
Chris
Zach
Karl
Zoe
Simon
John
Anton
>>>
The new style of for loop you used in these steps does not require any read methods.
This is because you can use a file object variable as a method for iterating through the file.
One item that has been very sloppily handled so far in this tutorial is closing files. Notice
in step 25 that you simply quit out of the Python interactive shell, without doing any
proper file closure. In the next section, you learn how to properly close a file.
Closing a File
When a file is opened in almost any program, it is considered good form to close it before
you exit that program. This is true in Python scripting as well. The general syntax for
closing an opened file is
filename_variable.close()
In Listing 11.12, the temperature file is opened and then immediately closed. Whether or
not the file is opened is tested twice by the .closed method.
Listing 11.12 Closing the Temperature File
Click here to view code image
pi@raspberrypi:~$ python3
[]
>>> temp_data_file=open(/home/pi/data/May2015TempF.txt,r)
>>>
>>> temp_data_file.closed
False
>>>
>>> temp_data_file.close()
>>>
>>> temp_data_file.closed
True
>>>
Python automatically closes a file if its filename variable is reassigned to another file.
However, when youre writing to a file, closing a file can be critical. This is due to the fact
that the operating system buffers the write methods in memory. The data is written to the
file only when the buffer reaches a certain level. When a file is closed in Python, the
buffer in memory is automatically written to the file, regardless of whether it is full. Not
properly closing a file could leave your files data in a very interesting state!
You can see why it is considered good form to properly close a file, especially if it is being
written to. This leads to the next topic of this hour: writing to a file.
Writing to a File
A file can be opened for writing only, or it can be opened to be read and written. The open
mode for writing a text file is either w or a, depending on whether you want to create a
new file or append to an old one. Adding a plus symbol (+) at the end of either the w or a
open mode enables you to both read and write to the file.
pi@raspberrypi:~$ ls /home/pi/data
friends.txt May2015TempF.txt
pi@raspberrypi:~$
pi@raspberrypi:~$ python3
[]
>>> import os
>>> os.listdir(/home/pi/data)
[May2015TempF.txt, friends.txt]
>>>
>>> ctemp_data_file=open(/home/pi/data/May2015TempC.txt,w)
>>>
>>> os.listdir(/home/pi/data)
[May2015TempF.txt, May2015TempC.txt, friends.txt]
>>>
In Listing 11.13 the file May2015TempC.txt is nonexistent before the open function
is used. After the file is opened, using the w mode, the text file is created.
After the file is properly opened in the correct mode, you can begin to write data to it
using the .write method. Using the example from Hour 9, Dictionaries and Sets,
again, a files stored Fahrenheit temperatures are converted to Celsius and written to the
new file.
In Listing 11.14, the Fahrenheit file May2015TempF.txt is open for reading, so the
temperatures in it can be converted to Celsius. The Celsius file May2015TempC.txt
also is opened for writing. Included is a for loop for reading the Fahrenheit temperatures
from the Fahrenheit file. Notice that the for loop is the more elegant file reading loop
version used in this hours previous Try It Yourself section.
Listing 11.14 Writing to the Celsius Temperature File
Click here to view code image
pi@raspberrypi:~$ python3
[]
>>>
>>> ftemp_data_file=open(/home/pi/data/May2015TempF.txt,r)
>>>
>>> ctemp_data_file=open(/home/pi/data/May2015TempC.txt,w)
>>>
>>> date_count=0
>>> for ftemp_data in ftemp_data_file:
#
ftemp_data=ftemp_data.rstrip(\n)
#
ftemp_data=ftemp_data[2:len(ftemp_data)]
#
ftemp_data=ftemp_data.lstrip( )
#
ftemp_data=int(ftemp_data)
#
ctemp_data=round((ftemp_data - 32) * 5/9, 2)
#
date_count += 1
#
ctemp_data=str(date_count) + + str(ctemp_data) + \n
#
ctemp_data_file.write(ctemp_data)
8
8
8
[]
9
9
9
>>> ftemp_data_file.close()
>>> ctemp_data_file.close()
>>>
In the preceding example, after the Fahrenheit temperature is read into the variable
ftemp_data, some processing is needed to pull out the temperature from the read-in
data. First, the newline escape sequence is stripped off using .rstrip. The temperature
is obtained using string slicing. (String slicing was covered in Hour 10.) Before
calculations start, any preceding blank spaces are stripped off using .lstrip, and the
temperature data character string is turned into an integer using the int function.
The temperature is converted from Fahrenheit to Celsius using the proper math equation
and the round function, as shown in Listing 11.14. Before the data can be written to the
new Celsius text file, it must be converted from floating point back to a character string
using the str function. All the data, a needed space, and a /n are stored in the character
string, ctemp_data, because the .write method can accept only one argument.
Remember that a newline escape sequence (/n) is often necessary at a strings end to act
as a data separator. After all that, the data is written to the new file using the .write
method, as was shown in Listing 11.14.
By the Way: What Are Those Numbers?
Listing 11.14 contains a partial string of 8s and 9s after the .write method in the
code. This is because the .write method displays to output how many characters
it wrote to a text file (or how many bytes it wrote to a binary file).
After all the data has been read from the Fahrenheit file, processed, and written out to the
Celsius file, the files are closed. Remember that closing files is important when writing to
a file, and its considered good form. Listing 11.14 shows that the files are closed using
the .close method.
To check whether all was correctly handled in Listing 11.14s code, the Celsius files
contents are displayed via the command line in Listing 11.15. The Fahrenheit temperature
data was properly read in, converted, and written out to the Celsius file, as the results in
Listing 11.15 show.
Listing 11.15 The Celsius Temperature File
Click here to view code image
Note that each Celsius temperature has the day of the month it was recorded and is
displayed in floating-point format. Also notice that each temperature is on its own line in
the text file. This is due to the following statement, used in Listing 11.14, which tacks a
newline \n escape sequence onto each Celsius temperature data strings end:
Click here to view code image
ctemp_data=str(date_count) + + str(ctemp_data) + \n
pi@raspberrypi:~$ python3
Python 3.2.3 (default, Mar 1 2013, 11:53:50)
[]
>>> ctemp_data_file=open(/home/pi/data/May2015TempC.txt,a)
>>>
This open statements mode setting keeps the files original data from being overwritten.
The append mode (a) sets the file pointer to the files end. Thus, any .write methods
that occur start writing at the files bottom and no data is lost.
Dont let it throw you that a number displays after each name you enter.
Remember that the .write method shows the number of characters it wrote to a
file. (Have you figured out who these people are yet?)
12. So that you can now read the file from the beginning, reset the file pointer to the
start of the file by typing my_friends_file.seek(0) and pressing Enter.
13. Type for my_friend in my_friends_file: and press Enter to create
a for loop to read the new populated friends file using keyboard input. Notice that
there is no need to close and reopen the file. This is because in step 5, the file
was opened with the mode w+, which allows you to write to the file and read it.
14. Press the Tab key once and then type print(my_friend, end= ). This
causes the data read into the Python script from the file to be displayed to your
screen.
15. Press the Enter key twice. You should see the friends names from the
friends.txt file displayed to the screen.
16. Close the friends.txt file by typing my_friends_file.close() and
pressing the Enter key. Now the file is properly closed.
17. Just to double-check, type my_friends_file.closed and press the Enter
key. If the file is truly closed, you should receive the word True. If you get
False, repeat step 16.
18. Press Ctrl+D to exit the Python interactive shell.
19. If you want to power down your Raspberry Pi now, type sudo poweroff and
press the Enter key.
Creating the /home/pi/data/friends.txt file this time was much easier than it
was in the last Try It Yourself section. By now you should have a good handle on how
to open, close, read, and write data files.
Summary
In this hour, you read about using files in Python. You saw how to open and close a file.
Also, you were introduced to Python statements and structures that enable you to read
from a file and write to a file. You got to try both writing to a file in the command line and
reading it and then writing to a file within Python and reading it. In Hour 12, Creating
Functions, you investigate how to create your own Python functions. This means you are
starting to move into more advanced Python concepts!
Q&A
Q. Why is an absolute directory reference used in Table 11.2?
A. An absolute directory reference is needed in Table 11.2. Remember that a relative
directory reference depends on where you are currently located in the Linux
directory structure. Thus, when the location is unknown, absolute directory
references, such as /home/pi/py3prog, /home/pi/temp, and
/home/pi/data are used. Absolute directory references are commonly used in
documentation.
Q. What is pickling?
A. Pickling is a method of preserving vegetables, such as cucumbers, in a salty vinegar
solution. But you are probably asking about pickling data, mentioned in Table 11.1,
and not vegetables.
Pickling is a method of transforming a Python object, such as a dictionary, into a
series of bytes for storage into a file. Turning an object into a series of bytes is
called serializing an object. You need to import the pickle function to perform
pickling of objects.
The advantage of pickling is that it enables you to quickly and easily handle objects.
A pickled object can be read from a file into a single variable. The disadvantage is
that pickling has no security measures built around it. Therefore, you could cause a
system to be compromised by using it.
Q. How can I keep the .write method from displaying the number of characters
it has written during the running of a Python script?
A. You can use a cheat method. Import the nonbuilt-in function sys. Then before
using your .write method, redirect the terminal output by typing in the following
statement: sys.stdout=open(/dev/null, w). This sends the
characters written as output to nowhere. However, be very careful using a feature
like this! You also will send any error messages and all output to nowhere as well!
Q. I cant figure it out. Who are those people in the friends.txt file?
A. Heres a hint: The names are sci-fi related.
Workshop
Quiz
1. The os function is a built-in function. True or false?
2. An absolute directory reference in Raspbian always begins with the _______ symbol.
3. Which os method displays your present working directory?
4. To access a files data in a Python script, the built-in _______ function is used.
5. To open a file to be both read and written, which mode should be used in the open
function statement?
a. w+
b. r&w
c. r+
6. Opening a file in write mode causes a files contents to be deleted. True or false?
7. Which method allows you to read a files entire contents at one time?
a. .readline()
b. .read()
c. .readfile()
8. It is good form to close your file when you are done with it to ensure the files data
does not get corrupted. True or false?
9. The _______ method displays the file pointers current position.
10. Which two file object methods can be used to read a text file in a random-access
manner?
Answers
1. False. The os function is not a built-in function. You must import it to use its various
methods. To import the os function, you use the Python statement import os.
2. An absolute directory reference in Raspbian always begins with the / symbol. An
example of this is /home/pi/data.
3. The .getcwd() method displays your present working directory.
4. To access a files data in a Python script, the built-in open function is used.
5. This is a trick question! Both answers a and c are correct. Remember that tacking on
the plus sign (+) to either r or w enables the file to have the other option done to it as
well. Therefore, w+ lets you read and write to a file, and r+ also lets you read and
write to a file.
6. True. Opening a file in write mode (w) or write/read mode (w+) causes a files
contents to be deleted.
7. B is the correct answer. The .read() method allows you to read a files entire
contents at one time.
8. True. It is good form to close your file when you are done with it to ensure the files
data does not get corrupted.
9. The .tell method displays the file pointers current position.
10. The .read and .seek file object methods can be used to read a text file in a
random-access manner. You use the .seek method to put the file pointer in the
correct position in the file. You use the .read method to read a particular number of
characters from the file.