25

im reading a csv file and then writing a new one:

import csv

with open('thefile.csv', 'rb') as f:
  data = list(csv.reader(f))

import collections
counter = collections.defaultdict(int)
for row in data:
    counter[row[11]] += 1

writer = csv.writer(open('/pythonwork/thefile_subset1.csv', 'w'))
for row in data:
    if counter[row[11]] >= 500:
       writer.writerow(row)

for some reason i cannot get the csv.writer to close the file. when i open the file it opens it as READ ONLY because it says that is still open.

how do i close thefile_subset1.csv after i am done with it?

BartoszKP
  • 33,416
  • 13
  • 100
  • 127
Alex Gordon
  • 54,010
  • 276
  • 644
  • 1,024

5 Answers5

36
with open('/pythonwork/thefile_subset1.csv', 'w') as outfile:
    writer = csv.writer(outfile)
    for row in data:
        if counter[row[11]] >= 500:
           writer.writerow(row)
John La Rooy
  • 281,034
  • 50
  • 354
  • 495
25

You can break out the open command into its own variable, so that you can close it later.

f = open('/pythonwork/thefile_subset1.csv', 'w')
writer = csv.writer(f)
f.close()

csv.writer throws a ValueError if you try to write to a closed file.

Donald Miner
  • 37,251
  • 7
  • 89
  • 116
6

close the file, not the csv writer. To do this, you'll need to open the file first before instantiating your writer rather than keeping it all in one line.

import csv
import collections

with open('thefile.csv', 'rb') as f:
    data = list(csv.reader(f))

counter = collections.defaultdict(int)
for row in data:
    counter[row[11]] += 1

f.close()  # good idea to close if you're done with it

fSubset = open('/pythonwork/thefile_subset1.csv', 'w')
writer = csv.writer(fSubset)
for row in data:
    if counter[row[11]] >= 500:
        writer.writerow(row)

fSubset.close()

Also, I would suggest keeping your imports at the top of the script and closing the first file when you're done with it.

Jim Clouse
  • 8,304
  • 5
  • 30
  • 25
  • 1
    `f.close()` is unnecessary. Why not use `with open` for `fSubset`? – David Cullen Aug 18 '16 at 21:18
  • 1
    I'm working with a class that uses (does not extend!) a csv writer, with the writer being shared across several methods indefinitely. The "with open as" pattern doesn't fit all use cases. Ensuring that there is a way to clean up the open file descriptor is important for a long running process. – Jeff W Feb 13 '20 at 12:46
5

Force the writer to clean up:

del writer
James
  • 6,619
  • 2
  • 16
  • 18
  • 2
    -1 There's no guarantee that the cleanup action will happen immediately (it depends on which implementation of Python you're using). – Greg Hewgill Jul 27 '10 at 21:00
  • 2
    The [`del` statement](http://docs.python.org/reference/simple_stmts.html#grammar-token-del_stmt) *only* removes the name binding: "Deletion of a name removes the binding of that name from the local or global namespace, depending on whether the name occurs in a global statement in the same code block." It doesn't say anything about when cleanup might happen. – Greg Hewgill Jul 27 '10 at 21:04
  • @James Roth, while this probably will work for CPython, it is a really bad idea. It won't work for Jython for example as `writer` will not be closed until it is gc'd. Python says nothing about when the file would be closed by deleting the reference to `writer`. More importantly though it's disguising the intent, which is to close the file which harms readability – John La Rooy Jul 27 '10 at 21:38
  • oy vey james this is really a horrific idea indeed, horrificable – Alex Gordon Jul 27 '10 at 22:28
  • you might be able to redeem yourself: http://stackoverflow.com/questions/3348460/python-getting-rid-of-extra-line – Alex Gordon Jul 27 '10 at 22:28
  • Haha, okay, okay, I was wrong. This was a lame attempt to push my score over 1000! – James Jul 28 '10 at 15:49
  • 2
    +1 Only answer that fixes my problem. All the others are retroactive (i.e. here's what you should do in the future). Should be noted that you should call `gc.collect()` immediately afterward for manually starting garbage collection. – Muhd Aug 23 '12 at 21:17
-2

Look at the difference:

with open('thefile.csv', 'rb') as f:
    data = list(csv.reader(f))

vs:

writer = csv.writer(open('/pythonwork/thefile_subset1.csv', 'w'))
pillmuncher
  • 9,824
  • 2
  • 32
  • 33