1

Using Python 3 on a windows machine:

I have a function to take a list of lists and open it as a csv file using my default application (excel). Despite closing the file after writing, I get a 'locked for editing' message when excel starts.

def opencsv(data):
        """saves a list of lists as a csv and opens"""
        import tempfile
        import os
        import csv
        handle, fn = tempfile.mkstemp(suffix='.csv')
        with open(fn,"w", encoding='utf8',errors='surrogateescape',\
                      newline='') as f:
            writer=csv.writer(f)
            for row in data:
                try:
                    writer.writerow(row)
                except Exception as e:
                    print ('Error in writing row:',e)
            f.close()

        url = 'file://' + fn.replace(os.path.sep, '/')
        os.startfile(fn)
opencsv([['d1','d2'],['d3','d4','d5']])

error window

How can I fix this?

deseosuho
  • 958
  • 3
  • 10
  • 28
  • 1
    If you use the `with open(fn) ..` construction, you actually should't need to close the file at all. Don't think that'll fix it though. – Gijs Oct 14 '15 at 15:03
  • 1
    Can you open the same file after the process has ended? – Gijs Oct 14 '15 at 15:04
  • 1
    mkstemp creates the file and returns the file descriptor in a tuple: "mkstemp() returns a tuple containing an OS-level handle to an open file (as would be returned by os.open()) and the absolute pathname of that file, in that order." You don't need to open it again, just "csv.writer(handle)". That means you won't be able to declare most of those open options though. – swstephe Oct 14 '15 at 15:05
  • You create 'url' but don't use it. Maybe you wanted os.startfile(url) – Marichyasana Oct 14 '15 at 15:12
  • @swstephe: Sounds like an answer to me. The `handle` is still open. – Karoly Horvath Oct 14 '15 at 15:12
  • does f.closed evaluate as True? That would have told you if you'd actually closed the file with f.close(). – BlivetWidget Oct 14 '15 at 15:13
  • @swstephe This seems to be it. I'm struggling with the documentation on handles. It seems that in `handle, fn = tempfile.mkstemp(suffix='.csv')` handle is an integer that in some way represents the file to the os. It isn't an object though, so I can't use csv.writer(handle). I'm having trouble accessing the object that mkstemp is opening. – deseosuho Oct 14 '15 at 15:24
  • Okay, that's right. You need to convert to a file object. Use "f = os.fdopen(handle)" and "csv.writer(f)". [See this link](http://stackoverflow.com/questions/168559/python-how-do-i-convert-an-os-level-handle-to-an-open-file-to-a-file-object) – swstephe Oct 14 '15 at 15:32

1 Answers1

2

Answer from swstephe's input:

The issue is that mkstemp opens the file and associates it with an os handle. In my original code I was not closing this file properly. See below for updated code.

def opencsv(data):
    """saves a list of lists as a csv and opens"""
    import tempfile
    import os
    import csv
    handle, fn = tempfile.mkstemp(suffix='.csv')
    with os.fdopen(handle,"w", encoding='utf8',errors='surrogateescape',\
                  newline='') as f:
        writer=csv.writer(f)
        for row in data:
            try:
                writer.writerow(row)
            except Exception as e:
                print ('Error in writing row:',e)

    print (fn)
    os.startfile(fn)
deseosuho
  • 958
  • 3
  • 10
  • 28