FILE ACCESS – built-in methods

Python has decent, though modest, file access capabilities which can be expanded considerably using modules like os, os.path, shutil, and csv – all of which are available in the standard library. (See Reading and Writing Files 102.) That said, if you are willing to do just a little work with data strings (strings are all that native Python file access methods read and write) you can do quite a lot. On this page, devoted to the native Python methods, we will also note some possibly helpful string methods and a couple of techniques that might speed things along. Here is a quick reference:

File Access Methods
open(filename,mode) – creates a file object
Example: aFile=open(“file or complete file path”, mode)

modes are:
r – read only w – write only
r+ – read and write a – append
b – appended to the above open in binary mode

.read() – returns the entire file; past EOF empty string ” is returned
.read(size) – returns size bytes of the file
.readline() – reads a single line; \n is left at end of the string; if an empty string is returned the EOF has been reached; if ‘\n’ is returned it is just an empty line in the file
aFile.readlines() – reads the file into a list of lines;
.write(str) – writes str to a file and returns number of characters written; convert non-str to str
.tell() – only useful in binary mode: returns bytes from beginning
.seek(offset, from_what) – changes file position adding offset to from_what value: (0) beginning of file, (1) current position, (2) end of the file; text files only work with 0 so from_what can be skipped
.close() – close file and release memory
https://docs.python.org/3.3/tutorial/inputoutput.html#reading-and-writing-files

A Few String Methods Useful with File Access Functions
https://docs.python.org/3.3/library/stdtypes.html#str.splitlines
Since accessing a text file returns either a string or a list of strings, the following string methods may be particularlly useful when dealing with files:
.splitlines([keepends]) – makes a list of lines in a string breaking at newline boundaries; line breaks are not maintained unless keepends=True
.isprintable() – has no embedded escape characters – including \n at the end.
.strip([chars]) – removes leading and trailing characters – does not change string
.split(sep=None, maxsplit=-1) return words in a string as a list, using sep as delimiter.
.rjust(width[,fill character]) – right justify filling with fill character
.ljust(width[,fill character]) – left justify filling with fill character

The first obstacle to most file based applications is where to find or put your data file. That is generally an entirely different problem from using disk based files, so in the following examples we will be assuming some specific file locations on some random user’s computer. You can do the substitutions yourself based on the example(s) we show. Here goes:

Reading from a File

Constructing a Path

mypath='D:\\Documents\\Python3\\fileinout\\' #NOTE construction of path
#ALTERNATIVELY could construct as: mypath=r'D:\Documents\Python3\fileinout\'
file2access = "Jack.txt"
testfile=mypath+file2access

In line 1 we build a path object.  Doubling the ‘\’ is how we get it to let us add slashes instead of treating them as escape codes. Now it is all primed to plug in a file.
Line 2 names the file we want.
Line 3 joins them so we have a complete, foolproof, path to use.

Opening a File Object

The following is mostly about the importance of using “with”.  That said, “with” may eventually be superfluous. Why? Glad you asked. The relatively new pathlib.Path methods .read_text and .write_text, when called, open the file, do their business, and then close the file. So “wala!” – no more “with”, no more “close”.  But for now…

assuming “testfile” is created as above…

with open (testfile,’r’) as Jack:

…and that is all there is to it to establish communications between your program and your hard drive. The use of “with” is so effective that you can hardly find any examples of opening and using files that are not structured this way. The with statement above lets us

  • (1) establish connection to our disk (the code called with open),
  • (2) identify the file we want,
  • (3) establish our read and write permissions (the ‘r’ says you only want to read the file),
  • (4) lets us name the activation of all of this activity to simplify future code (as Jack), perhaps most importantly
  • (5) with assures automatic closure of the file when we are finished. If the file is not closed, you can really screw stuff up.Many of the following examples assume these first four lines and for brevity’s sake they won’t be repeated with the exception of the next example. Now that we have set it up, lets do something with it:

Accessing the File Once Opened

    print(Jack.read())

All together it looks like this:

mypath='D:\\Documents\\Python3\\fileinout\\'   #NOTE construction of path
file2access = "Jack.txt"
testfile=mypath+file2access
with open(testfile,'r') as Jack:
    print(Jack.read()) 

…..an running it produces:
====== RESTART: D:\Program Files (x86)\Python\TempTest\temptestfile.py ======
Jack Spratt
could eat
no fat.
His Wife
could eat
no lean.
>>>
So from looking at the output we see that our file held six lines that we retrieved with a new line (/n) after each. Now we can see where the string methods come in handy. Suppose we wanted these lines all stuffed into a list? We can get rid of the /n (line breaks) and the file will be printed out as a comma separated list with the text lines in quotes. Let’s change that print line to use .splitlines() to do that:

    print(Jack.read().splitlines())
 

…..produces:
=========== RESTART: D:/Documents/Python3/fileinout/fileIOtests.py ===========
[‘Jack Spratt’, ‘could eat ‘, ‘no fat.’, ‘His Wife’, ‘could eat’, ‘no lean.’]

Of course, looking toward a practical application, we could read and process a line at a time straight from the file:

    for line in Jack:
        print(line, end="")
        if line == "could eat\n":  #Note the \n – without which it will not compare!
            print('found line "could eat" followed by: \n',end="-->") 

….would give us:
====== RESTART: D:\Program Files (x86)\Python\TempTest\temptestfile.py ======
Jack Spratt
could eat
found line “could eat” followed by:
->no fat.
His Wife
could eat
found line “could eat” followed by:
->no lean.

Actually, To get all the lines from a file into a list all we have to do is use EITHER:
file.readlines() OR list(file), i.e, print(Jack.readlines()) OR print(list(Jack)) either one will yield:
=========== RESTART: D:/Documents/Python3/fileinout/fileIOtests.py ===========
[‘Jack Spratt\n’, ‘could eat\n’, ‘no fat.\n’, ‘His Wife\n’, ‘could eat\n’, ‘no lean.’]

The “with” structure is highly recommended but not essential provided you remember to manually close your file. Once our “testfile” path and file variable has been defined, the following works just fine.

Jackfile = open(testfile,'r')
print(Jackfile.readlines())
Jackfile.close     #must close the file “manually”

Writing to a File

Let’s give Jack a rest and employ one of his fellow co-workers in the nursery rhyme industry to help us demo writing to a file. We start out almost exactly the same way. The exceptions are that the first two lines of text below define strings that hold the text we want to write to disk.
The next three lines, as we did when reading, construct our file path, and puts it in a variable called myfile.
The sixth line opens our with structure with a ‘w’ to establish our permission to write and names the object ‘workfile’.
Line seven creates our file on disk and writes our first string, “maryText”, to that file. The “with” structure then automatically closes the file.
Line eight prints a message just to prove we are out of the with structure and moving on with our program.
Line nine opens our “workfile” object again, but this time with an “a” to tell Python we want to append something to an existing file. If the file does not already exist you will get an error – error checking is left to the reader’s exercise.
Line ten appends our “maryText2” string variable to the “Mary.txt” file we have previously created, and the with structure auto closes the file.
The last line just confirms we are finished.

maryText="Mary had a little lamb, its fleece was white as snow, "
maryText2="and everywhere that Mary went, the lamb was sure to go."
mypath="D:\\Documents\\Python3\\fileinout\\"    #NOTE PATH CONSTRUCTION
myfile="Mary.txt"
MaryPath = mypath + myfile
with open(MaryPath,'w') as workfile:
    workfile.write(maryText)
print("Completed writing first line to file.")
with open(MaryPath,'a') as workfile:
    workfile.write(maryText2)
print(myfile + " should now have both lines and be closed.")
 

…..opening this in a note pad program gives you a single string – it’s a one line file.

We don’t have to be stuck with it as a single line; with a little help from some string methods:

for i in range (len(maryText.split(','))):
   print(maryText.split(',')[i].strip())

…..we can get
Mary had a little lamb
its fleece was white as snow
and everywhere that Mary went
the lamb was sure to go.
Notice we did lose the comma separators in the process – in many cases this is a good thing.

Or we could just write it as a four line file to start with, with a little help from some string methods:

maryText="Mary had a little lamb, its fleece was white as snow, and everywhere that Mary went, the lamb was sure to go."
mypath="D:\\Documents\\Python3\\fileinout\\"
myfile=r"Mary.txt"
MaryPath = mypath + myfile
with open(MaryPath,'w') as workfile:
    for i in range(len(maryText.split(','))):
        workfile.write(maryText.split(',')[i].strip()+'\n') 

…..and when opened with a text editior we get:

Mary had a little lamb
its fleece was white as snow
and everywhere that Mary went
the lamb was sure to go.