2

I'm using a program (follows) to see the similarities in certain columns between two CSV files, then create a third when data matches certain specifications (two columns are the same but the third is not) so that I can update an e-mail list.

When I try to open the results.csv file after running the program however, Windows Excel will only open the program in read-only mode.

Any thoughts?

Here's my code:

import csv

sample_data = open("sample.csv", "r")
lib_data = open("library.csv", "r")
csv1 = csv.reader(sample_data)
csv2 = csv.reader(lib_data)

results = open("results.csv", "w")
res_csv = csv.writer(results)

limit = 1071
limit2 = 1001

x = 0
y = 0

while (y != limit):
    row1 = csv1.__next__()
    while (x != limit2):
        row2 = csv2.__next__()
        if (row1[0] == row2[3] and row1[1] == row2[2] and row1[2] != row2[5]):
            print ("SAMPLE:")
            print (row1[0], ", ", row1[1], ", ", row1[2])
            print ("LIBRARY:")
            print (row2[3], ", ", row2[2], ", ", row2[5])
            print("\n")
            res_csv.writerow(row1)
        x = x+1
    y = y+1
    x = 0
    lib_data.seek(0)
jcollado
  • 39,419
  • 8
  • 102
  • 133
James Roseman
  • 1,614
  • 4
  • 18
  • 24

5 Answers5

6

Use with to ensure files will be closed properly:

with open("sample.csv", "r") as sample_data:
    with open("library.csv", "r") as lib_data:
        with open("results.csv", "w") as results:
            # other code

You can even put several variables into one with if you're using Python >= 2.7.

Jan Pöschko
  • 5,412
  • 1
  • 28
  • 28
4

Close the file

results.close()

Juuso Ohtonen
  • 8,826
  • 9
  • 65
  • 98
2

Having the same problem when using python 2.7 and none of the solution solved my problem. Solution: just add "quoting", for example:

res_csv=csv.writer(results,quoting=csv.QUOTE_ALL). 

This solves my problem

Scransom
  • 3,175
  • 3
  • 31
  • 51
Jong
  • 21
  • 1
0

You should try opening the file with specific permissions by importing os module and using file permission flags. Here is a link to a similar post - Write file with specific permissions in Python

Community
  • 1
  • 1
anu.agg
  • 197
  • 13
0

You are leaving the files open. To close them, note that you have to first delete the csv object that uses the open file handle! Because of this, I rarely open the file handle separately from the csv reader/writer object.

So a better way to do this would be:

import csv

csv1 = csv.reader(open("sample.csv", "rb"))
csv2 = csv.reader(open("library.csv", "rb"))

res_csv = csv.writer(open("results.csv", "w"))

limit = 1071
limit2 = 1001

x = 0
y = 0

while (y != limit):
    row1 = csv1.__next__()
    while (x != limit2):
        row2 = csv2.__next__()
        if (row1[0] == row2[3] and row1[1] == row2[2] and row1[2] != row2[5]):
            print ("SAMPLE:")
            print (row1[0], ", ", row1[1], ", ", row1[2])
            print ("LIBRARY:")
            print (row2[3], ", ", row2[2], ", ", row2[5])
            print("\n")
            res_csv.writerow(row1)
        x = x+1
    y = y+1
    x = 0
    lib_data.seek(0)

del csv1
del csv2
del res_csv

This makes it more explicit that you have to delete the csv to close the file handle. Also note that the official csv docs state to open files in binary mode, to avoid line ending issues.

EDIT

As noted in the comments, I'm wrong about with closing the file even if the csv handle is still available. A quick test verified this, so proper usage is:

import csv

with open("sample.csv", "rb") as sample:
    csv1 = csv.reader(sample)
    with open("library.csv", "rb") as lib_data: # the csv handle for this file is never used
        with open("results.csv", "wb") as results:
            res_csv = csv.writer(results)

            limit = 1071
            limit2 = 1001

            x = 0
            y = 0

            while (y != limit):
                row1 = csv1.__next__()
                while (x != limit2):
                    row2 = csv2.__next__()
                    if (row1[0] == row2[3] and row1[1] == row2[2] and row1[2] != row2[5]):
                        print ("SAMPLE:")
                        print (row1[0], ", ", row1[1], ", ", row1[2])
                        print ("LIBRARY:")
                        print (row2[3], ", ", row2[2], ", ", row2[5])
                        print("\n")
                        res_csv.writerow(row1)
                    x = x+1
                y = y+1
                x = 0
                lib_data.seek(0)
Spencer Rathbun
  • 14,510
  • 6
  • 54
  • 73
  • Are you sure that del can be trusted to have that effect? IIRC del in Python only deletes the name, which lowers the number of references by one, which might if there are no other references (depending on implementation details) result in it being finalized (or whatever the right word is) at some point in the future but there are no guarantees. – DSM Jan 25 '12 at 20:21
  • But for readability, there is nothing wrong with an explicit close is there? – octopusgrabbus Jan 25 '12 at 20:32
  • @DSM I've never had a problem with it, but YMMV. – Spencer Rathbun Jan 25 '12 at 20:40
  • @octopusgrabbus If you find it easier to read with the explicit close, that wouldn't hurt either. Just realize that you have to `del` the csv object first, or you won't be allowed to close the file handle. – Spencer Rathbun Jan 25 '12 at 20:41
  • seek won't work without the handles opened separately, which is why I did it this way. Maybe there's something flawed with my understanding of the CSV module however. – James Roseman Jan 25 '12 at 20:44
  • As stated above. del only deletes the reference. In python there's no guarantee that an object is destructed (or the file immediately closed) at that point. It's up to the garbage collector. Use 'with' as shown in another answer. – Johan Lundberg Jan 25 '12 at 22:27