Unable to Zip due to GDB lock

1722
3
09-01-2016 06:58 AM
ScottFierro2
Regular Contributor

I am trying to automate a process to take a directory given by the user which contains a file geodatabase and zip it with only the relative path being retained. Intended output is a ZIP that contains just the final folder with the FGDB inside of it.

The workflow is to take a feature class from SQL SDE and use "Feature Class to Feature Class" tool to load desired data into the FGDB. Next perform the zip below. When running this it returns this message:

Traceback (most recent call last):

File "C:\arcgisserver\ETL_Scripts\Scripts\Zipdir.py", line 19, in <module>

zipdir(directory, zip)

File "C:\arcgisserver\ETL_Scripts\Scripts\Zipdir.py", line 13, in zipdir

ziph.write(os.path.relpath(os.path.join(root, file), os.path.join(path, '..')))

File "C:\Python27\ArcGIS10.2\Lib\zipfile.py", line 1033, in write

st = os.stat(filename)

WindowsError: [Error 3] The system cannot find the path specified: u'Output\\Output.gdb\\a00000001.freelist'

This folder remains unable to be zipped until I close out of ArcCatalog which removes the .lock file from within the .gdb. This isn't an acceptable workflow to have to do in order to perform the zip as this is 1 step of about 15+ that needs to be able to be published into a service for automation. The code below is what I am using that creates this issue. Thanks for any assistance.

import os, arcpy, zipfile

directory = arcpy.GetParameterAsText(0)
outputFile = arcpy.GetParameterAsText(1)


def zipdir(path, ziph):
    #ziph is zipfile handle
    for root, dirs, files in os.walk(path):
        for file in files:
         if not file.endswith('.lock'):
             ziph.write(os.path.relpath(os.path.join(root, file), os.path.join(path, '..')))
          


if __name__ == '__main__':
     zip = zipfile.ZipFile(outputFile, 'w', zipfile.ZIP_DEFLATED)
     zipdir(directory, zip)
     zip.close()
Tags (2)
0 Kudos
3 Replies
RebeccaStrauch__GISP
MVP Esteemed Contributor

Sorry I don't have time to look at your issue specifically, but a couple things to try, and two variations to zip funtions (i've decided to use the zipws for the script I'm working on....zipping shapes in my case)

  • add a few print statements to see what it things the args/paths are
  • add a       time.sleep(10)      ....vary number as needed, after you copy to the FGDB and before you try anything else.  I've had to do that in one of my scripts to give the remote server in my case to finish the releasing even though my script had moved on.

Below are two different zip function I've found and modified.  I've using the second zip function one because if I set   keep = False   it will copy all my shapes to the "root" of the .zip.  Otherwise it was always putting the files in a folder within my .zip, which would not work for my purposes.

# functions only

import time
import os
import arcpy

def myMsgs(message):
     arcpy.AddMessage("{0}".format(message))
     print("{0}".format(message))
     
import sys, zipfile

def zip(src, toZip):
     #zf = zipfile.ZipFile("%s.zip" % (dst), "a", zipfile.ZIP_DEFLATED)
     zf = zipfile.ZipFile("{0}a.zip".format(os.path.join(path,toZip)), "a", zipfile.ZIP_DEFLATED)
     abs_src = os.path.abspath(src)
     for dirname, subdirs, files in os.walk(src):
          for filename in files:
               absname = os.path.abspath(os.path.join(dirname, filename))
               arcname = absname[len(abs_src) + 1:]
               #print 'zipping %s as %s' % (os.path.join(dirname, filename), arcname)
               myMsgs('zipping {0} as {1}'.format(filename, arcname))
               zf.write(absname, arcname)
     zf.close()


keep = False   # keep = True puts files in "path folder", False puts files at root of .zip
def zipws(path, toZip, fcBase):
     #zf = zipfile.ZipFile("%s.zip" % (toZip), "w", zipfile.ZIP_DEFLATED)
     zf = zipfile.ZipFile("{0}.zip".format(os.path.join(toZip, fcBase)), "a", zipfile.ZIP_DEFLATED)
     path = os.path.normpath(path)
     # os.walk visits every subdirectory, returning a 3-tuple
     #  of directory name, subdirectories in it, and file names
     #  in it.
     #
     for (dirpath, dirnames, filenames) in os.walk(path):
          # Iterate over every file name
          #
          for file in filenames:
               # Ignore .lock files
               #
               if fcBase in file and not file.endswith('.lock'):
                    myMsgs("Adding {0}...".format(os.path.join(path, dirpath, file)))
                    try:
                         if keep:
                              zf.write(os.path.join(dirpath, file),
                                    os.path.join(os.path.basename(path), os.path.join(dirpath, file)[len(path)+len(os.sep):]))
                         else:
                              zf.write(os.path.join(dirpath, file),            
                                    os.path.join(dirpath[len(path):], file)) 

                    except Exception, e:
                         arcpy.AddWarning("    Error adding {0}: {1}".format(file, e))

     return None

Things to try anyway.  I'm still working on my scripts, but those have been working for me for the zipping part of it.  hope this helps.

JoshuaBixby
MVP Esteemed Contributor

Since file geodatabases are folders, are you looking to have two folders, the file geodatabase and its parent folder?

ScottFierro2
Regular Contributor

Right, I finally figured it all out. Part of my issues was the code I was using to get just the relpath and not the absolute path was off. After fixing that I still had the locking issue. To get around it I used copymanagement to replicate the fgdb into a different folder. The new replicated folder doesn't have the lock so then I zip that up and added a delete at the end of process to remove the copy making the folder ready for the next run.