File Access 103: csv

Comma separated values are by far the most universal way of storing information in a file. This format’s stand-alone value is enhanced by the fact that Excel and Outlook both use, or at least can use, the csv format for simple and quick data exchange. In the examples below, we are always going to specify that we are using the “Excel” dialect of csv. This module also includes dictionary read/write objects which we will look at later. The csv module is called in the usual way:
import csv
….and all the “hard” parts you already know if you have read and worked through “File Access – built-in methods”. If you missed that page go review it now. csv just builds on those essentials. It will be convenient to build a path variable; we will wrap everything neatly in a “with” clause; and we will use the standard “.open” and “.close” methods plus their standard mode notations. Beyond that (assuming the correct command structure and syntax) there are just two primary functions which create objects whose methods do all the csv specific file manipulation.
Reading csv Files
csv.reader(csv file object [, dialect=’excel’] [, optional format parameter override]) – returns a “reader” object to iterate a file.

Reader object methods
.__next__() – reads the next line
.dialect – not functional as far as we tested this reader object
.line_num – returns number of lines read
.fieldnames – not functional as far as we tested this reader object

Writing cvs Files
csv.writer(csv file object, dialect=’excel’,formatting parameters) – returns a writer object; when structuring data to be written rememeber you are writing a series of Python lists. ‘None’ is written as empty string.

Writer object methods
.writerow(row) – write a row foratted by dialect
.writerows(rows) – write all rows
.dialect – a desc of the dialect in use


Reminder: Basic modes for all Python file interaction:
r – read (default)
w – write
a – append
r+ – read and write


Examples
*the following examples read some small data files you will not have but I will email them to you if you send a request to john@johnoakey.com. Otherwise you can just review the code for structure and syntax.

Reading and Formatting a Small Sample of csv Spreadsheet Data

 import csv
# read and format spreadsheet data
basePath='D:\\Documents\\Python3\\fileinout\\' #NOTE construction of path
dataFile = "TinySample.csv"  
wholeFilePath=basePath+dataFile 
print(wholeFilePath)
with open(wholeFilePath) as IRSdata:
    zipcodeSample=csv.reader(IRSdata,dialect='excel')
    header = zipcodeSample.__next__()
    nototal=True
    for column in header:
        print(column.rjust(14," "),end="")
    print()
    while nototal is True:
        dataline = zipcodeSample.__next__()
        if dataline[0]=="Totals":
            nototal=False
        for item in dataline:
            print(item.rjust(14," "),end="")
        print()

….yeilds…

“D:\Program Files (x86)\Python\python.exe” “D:/Program Files (x86)/Python/TempTest/csv r and format spreadsheet.py”
D:\Documents\Python3\fileinout\TinySample.csv
       ZIPHEAD          CODE   NOofReturns       Singles        Joints    HOHreturns    Exemptions    Dependents           AGI    NOofRetTot      Totl amt
         30002         30002         3,060         1,620           960           400         5,490         1,570       245,670         3,060       249,852
         30004         30004        25,890         9,990        12,910         2,420        58,280        21,910     3,426,425        25,890     3,472,749
         30005         30005        15,090         5,520         8,070         1,230        34,960        13,570     1,888,015        15,090     1,913,525
         30008         30008        13,010         5,900         3,270         3,520        27,480        11,680       481,115        13,010       486,924
         30009         30009         7,780         3,690         3,080           880        15,290         5,020       756,255         7,780       765,923
        Totals                      64,830        26,720        28,290         8,450       141,500        53,750     6,797,480        64,830     6,888,973
Process finished with exit code 0

Creating a New csv File and Writing or Appending to It

 import csv
basePath='D:\\Documents\\Python3\\fileinout\\' #NOTE construction of path
contactFile = "contacts.csv"
wholeFilePath=basePath+contactFile
headerlist=['Last','First','Addr1','Addr2','City','State','Zip'] #create our contact information header
contactInfoList=[] #create our contact information list container
#have the user input any info on the seven fields of our contact data
for colHead in headerlist:
    myinput = input(colHead +': ')
    contactInfoList.append(myinput)
try:
    with open(wholeFilePath,'r',newline='') as csvfile:
        csvfile.close()  #try  read  first  to  force  error  if  new  file - if error will go to except to create new file
        with open (wholeFilePath,'a',newline='') as csvfile:  # but if the file exists, then open  as  append
            csvfilewriter=csv.writer(csvfile, dialect='excel') #invoke the writer on the file we have defined
            csvfilewriter.writerow(contactInfoList)  # and write all the fields of data we gathered for one record
except:
    with open(wholeFilePath,'w',newline='') as csvfile:   #  if  new  establish  header and create  file
        csvfilewriter=csv.writer(csvfile, dialect='excel')
        csvfilewriter.writerow(headerlist) # just have to create header once, when we first create the file
        csvfilewriter.writerow(contactInfoList)

print('file completed')

…yields….well in this case it yields an explanation

The first time you run this program it will not find the specified file so the error forces the “except” routine where it creates the physical file on disk, puts in the header list and then writes the first record (which the user just input).

The second (and later of course) time the program will find the file you have already created and it just appends the newly entered information to it. Note that any error checking is left to your own devising.

Other Functions – for more information see: https://docs.python.org/3.5/library/csv.html#module-csv
.register_dialect(name[, dialect[, **fmtparams]])
.unregister_dialect(name)
.get_dialect(name)
.list_dialects()
.field_size_limit([new_limit])

Reading and Writing Dictionaries
The module also defines several classes, two of which are specifically for reading and writing dictionary type files. The process of creating and the usage of these objects is worthy of an entire discussion of its own, so see the module page for more information. Just for the record:
csv.DictReader(csvfile, fieldnames=None, restkey=None, restval=None, dialect=’excel’, *args, **kwds)
csv.DictWriter(csvfile, fieldnames, restval=”, extrasaction=’raise’, dialect=’excel’, *args, **kwds)

Other Classes

.dialect
.excel
.excel_tab
.unix_dialect
.Sniffer

csv Constants – see the module docs – Dialect.quoting

.QUOTE_ALL – quote all fields
.QUOTE_MINIMUM – only quote fields with special characters
.QUOTE_NONNUMERIC
.QUOTE_NONE