4

This is similar or identical to csv writer not closing file but I'm not 100% sure why my behaviour is different.

def LoadCSV:
    with open('test.csv', 'r') as csvfile:
        targetReader = csv.reader(csvfile, delimiter=',')
        for row in targetReader:
            ...

then finally in the function

csvfile.close()

This opens the test.csv file in the same direction as the script. Desired behaviour is for when the script has done what it's doing to the rows in the function, it renames the sheet to test.[timestamp] to archive it and watches the directory for a new sheet to arrive.

Later down the code;

os.rename('test.csv', "test." + time.strftime("%x") )

Gives an error that the file can't be renamed because a process is still using it. How do I close this file once I'm done? csvfile.close() doesn't raise an exception, and if I step through my code in interactive mode I can see that csvfile is a "closed file object." What even is that? Surely an open file is an object but a closed one isn't, how do I make my code forget this even exists so I can then do IO on the file?

Community
  • 1
  • 1
Elomis
  • 532
  • 3
  • 8
  • 18
  • 1
    The `with` block should automatically close the file when it goes out of scope. Try renaming it outside the scope of the `with` block – dpington Aug 25 '14 at 05:21
  • edit: It's outside the with block but inside the function, so it's outside the with. – Elomis Aug 25 '14 at 05:23
  • `os.rename('test.csv', "test." + time.strftime("%x") )` doesn't depend on `csvfile` being defined does it? – dpington Aug 25 '14 at 05:25
  • You do not need the file handle to rename the file, just the filename. `os.rename('test.csv'....` doesnt need anything defined :) – Qiau Aug 25 '14 at 05:25
  • Herp: no. Qiau: I may not need the handle but I still can't close the file as it's in use from the previous part where the handle was created. I use it by name in the close because the handle is private to the function. – Elomis Aug 25 '14 at 05:27
  • As the code is using the name test.csv in that block any time it is running, I have to ask, are other copies of the code running? i.e. is there a threading problem? – David Aug 25 '14 at 05:36
  • Are you sure that's your code the other process that is preventing windows from renaming the file? May be are there other processes that watch for files being created to analyze them (e.g. antivirus)? – 6502 Aug 25 '14 at 05:36
  • 1
    This is not valid Python code: `def LoadCSV:`, so please paste your actual code that you are using, rather than having us guess what is going on. – Burhan Khalid Aug 25 '14 at 05:55

2 Answers2

2

NOT FOR POINTS.

Code is not valid anyway, since your function name is wrong. If that was not intentional, better edit it or to produce a pseudo-replica of your code, rather than have us guess what the issue is.

To iterate, the issues with your code:

  1. def LoadCSV is not valid. def LoadCSV() is. Proof in following screenshot. Notice how the lack of () is showing syntax error markers.

enter image description here

  1. Fixing (1) above, your next problem is using csvfile.close(). If the code is properly written, once the code is out of the scope of with, the file is closed automatically. Even if the renaming part of the code is inside the function, it shouldn't pose any problems.

  2. Final word of warning -- using the format string %x will produce date-strings like 08/25/14, depending on locale. Obviously, this is erroneous, as a / is invalid in filenames in Windows (try renaming a file manually with this). Better to be very explicit and just use %m%d%y instead.

Finally, see the running code on my end. If your code is not structured like this, then other errors we cannot guess might arise.

enter image description here

Result as follows after running:

enter image description here

Code for reference:

import csv
import os
import time

def LoadCSV():
    with open("test.csv", "r") as csvfile:
        targetReader = csv.reader(csvfile, delimiter=",")
        for row in targetReader:
            print row
    new_name = "test.%s.csv" % time.strftime("%m%d%y")
    print new_name
    os.rename("test.csv", new_name)

LoadCSV()

Note that on my end, there is nothing that watches my file. Antivirus is on, and no multithreading obviously is enabled. Check if one of your other scripts concurrently watches this file for changes. It's better if instead of watching the file, the file is sent as an argument post-renaming to this other function instead, as this might be the reason why it's "being used". On the one hand, and this is untested on my side, possibly better to copy the file with a new name rather than rename it.

Hope this helps.

WGS
  • 13,969
  • 4
  • 48
  • 51
  • OK I was looking in the wrong place and your point 2 with a "final word of warning" was the kicker, the appending of the date was what was actually wrong. The file wasn't locked, it was trying to be renamed to a file that had slashes in the date which Windows threw a tantrum about. Thanks very much Nanashi – Elomis Aug 25 '14 at 08:26
  • Glad to know it helped you. I'm not too keen about the format strings that can be used in `strftime` myself, but when I read the docs and it showed that it's based on locale, I had a hunch it was either the `/` or a `.` that was part of what was messing you up. On the one hand, though, it throws the weirdest of errors. In your case, it's throwing a `file being used` error. On mine, it's a `file cannot be found` error. Funny how IO has a somewhat messed up Traceback. – WGS Aug 25 '14 at 08:43
0

When you are using a with block you do not need to close the file, it should be released outside the scope. If you want python to "forget" the entire filehandle you could delete it with del csvfile. But since you are using with you should not delete the variable inside the scope.

Try without the with scope instead:

csvfile = open('test.csv','r')
targetReader = csv.reader(csvfile, delimiter=',')
for row in targetReader:
    ....
csvfile.close()
del targetReader
os.rename('test.csv','test.'+time.strftime('%x'))

It might be the csv reader that still access the file when you are using a with block.

Qiau
  • 5,976
  • 3
  • 29
  • 40