Files¶
This section outlines basic file handling in Python, including file
utilities in the numpy
package.
File reading¶
Suppose we create a file with typical input data to our little demo program for evaluating the formula \(s(t)=v_0t + \frac{1}{2}at^2\):
v0 = 2
a = 0.2
dt = 0.1
interval = [0, 2]
We want to read the parameters in the file into Python variables and
create a table with columns of \(t\) and \(S(t)\) for \(t\in [0,2]\) with
steps of \(\Delta t=0.1\) (as specified by dt
and interval
in the file).
The code for reading the lines in the file, interpreting them, and assigning values to variables is given next.
infile = open('.input.dat', 'r')
for line in infile:
# Typical line: variable = value
variable, value = line.split('=')
variable = variable.strip() # remove leading/traling blanks
if variable == 'v0':
v0 = float(value)
elif variable == 'a':
a = float(value)
elif variable == 'dt':
dt = float(value)
elif variable == 'interval':
interval = eval(value)
infile.close()
The name of the file is here .input.dat
, and it is opened with the
parameter 'r'
for reading. The for loop for line in infile
will
read the lines from the file, one by one, and in the current line
is available in the string line
. To split a line into words separated
by a character ‘=’, we use line.split('=')
, resulting in a list of
the words. For example,
>>> line = 'v0 = 5.3'
>>> variable, value = line.split('=')
>>> variable
'v0 '
>>> value
' 5.3'
Note that there are blanks in the strings. Leading and trailing blanks
can be removed by variable.strip()
. We do this before comparing
the variable name with v0
, a
, etc.
It is important to note that value
(the text to the right of =
on
each line) is a string variable. We need to convert to a float
object to
get a variable that we can compute with.
The assignment interval = eval(value)
does some magic and deserve
an explanation: eval(s)
interprets the text in the string s
as
Python code. In the present example, value
is [0, 2]
and this
is interpreted as Python code, i.e., as a list, and interval
becomes
a name for a list object with content [0, 2]
.
A more modern Python way of opening files is
with open('.input.dat', 'r') as infile:
for line in infile:
...
Now it is not necessary to close the file as it will be automatically done
after the with
block.
File writing¶
Suppose we generate \(t\) and \(s(t)\) values in two lists, t_values
and
s_values
, and want to write these as a nicely formatted table to file.
The following code does the work:
outfile = open('table1.dat', 'w')
outfile.write('# t s(t)\n') # write table header
for t, s in zip(t_values, s_values):
outfile.write('%.2f %.4f\n' % (t, s))
Files intended for writing must be opened with a 'w'
parameter.
The key statement is outfile.write(s)
for writing a string to
a file (recall that while print
automatically adds a newline
at the end of the string to be printed, outfile.write(s)
does not
append a newline so s
must contain the newline).
The numpy
package contains a convenient function savetxt
for saving
tabular data. The data must be stored in a two-dimensional numpy
array.
The savetxt
function enables control of the format of the numbers
in each column (fmt
) through the printf syntax, a header can be
added (header
) and the header lines begin with a comment character
(comment
). The code reads
import numpy as np
# Make two-dimensional array of [t, s(t)] values in each row
data = np.array([t_values, s_values]).transpose()
# Write data array to file in table format
np.savetxt('table2.dat', data, fmt=['%.2f', '%.4f'],
header='t s(t)', comments='# ')
The tabular data in the file can be read back into a
numpy
array by the loadtxt
function:
data = np.loadtxt('table2.dat', comments='#')
Lines beginning with the comment character are skipped in the reading.
The resulting object data
is a two-dimensional array: data[i,j]
contains
row number i
and column number j
in the table, i.e., data[i,0]
holds the \(t\) value and data[i,1]
the \(s(t)\) value in the i
-th
row.