在Python中更新For Each循环

1 投票
2 回答
791 浏览
提问于 2025-04-16 03:17

下面的Python代码可以把一组文件压缩成一个文件。我只需要一个叫“Data”的文件地理数据库(就是一种基于文件的数据库),那么我该如何修改这个循环,只包含这个叫Data的文件地理数据库呢?更具体地说,文件地理数据库是以系统文件夹的形式存储的,里面包含一些二进制文件,用来存储和管理空间数据。所以我需要的是整个叫Data.gdb的系统文件夹。

非常感谢!

#**********************************************************************
# Description:
#    Zips the contents of a folder, file geodatabase or ArcInfo workspace
#    containing coverages into a zip file.
# Parameters:
#   0 - Input workspace
#   1 - Output zip file. It is assumed that the caller (such as the
#       script tool) added the .zip extension.
#
#**********************************************************************

# Import modules and create the geoprocessor
import sys, zipfile, arcgisscripting, os, traceback
gp = arcgisscripting.create()

# Function for zipping files 
def zipws(path, zip):
    isdir = os.path.isdir

    # Check the contents of the workspace, if it the current
    # item is a directory, gets its contents and write them to
    # the zip file, otherwise write the current file item to the
    # zip file
    #
    for each in os.listdir(path):
        fullname = path + "/" + each
        if not isdir(fullname):
            # If the workspace is a file geodatabase, avoid writing out lock
            # files as they are unnecessary
            #
            if not each.endswith('.lock'):
                # gp.AddMessage("Adding " + each + " ...")
                # Write out the file and give it a relative archive path
                #
                try: zip.write(fullname, each)
                except IOError: None # Ignore any errors in writing file
        else:
            # Branch for sub-directories
            #
            for eachfile in os.listdir(fullname):
                if not isdir(eachfile):
                    if not each.endswith('.lock'):
                        # gp.AddMessage("Adding " + eachfile + " ...")
                        # Write out the file and give it a relative archive path
                        #
                        try: zip.write(fullname + "/" + eachfile, \
                                       os.path.basename(fullname) + "/" + eachfile)
                        except IOError: None # Ignore any errors in writing file


if __name__ == '__main__':
    try:
        # Get the tool parameter values
        #
        inworkspace = sys.argv[1]
        outfile = sys.argv[2]     

        # Create the zip file for writing compressed data
        #
        zip = zipfile.ZipFile(outfile, 'w', zipfile.ZIP_DEFLATED)
        zipws(inworkspace, zip)
        zip.close()

        # Set the output derived parameter value for models
        #
        gp.setparameterastext(1, outfile)
        gp.AddMessage("Zip file created successfully")

    except:
        # Return any python specific errors as well as any errors from the geoprocessor
        #
        tb = sys.exc_info()[2]
        tbinfo = traceback.format_tb(tb)[0]
        pymsg = "PYTHON ERRORS:\nTraceback Info:\n" + tbinfo + "\nError Info:\n    " + \
                str(sys.exc_type)+ ": " + str(sys.exc_value) + "\n"
        gp.AddError(pymsg)

        msgs = "GP ERRORS:\n" + gp.GetMessages(2) + "\n"
        gp.AddError(msgs)

2 个回答

0

从这一行开始:

    zipws(inworkspace, zip)

你不想用这个函数来从多个文件创建压缩文件。看起来你只想用一个文件来创建压缩包。

把它换成这个。

     try: 
         zip.write(os.path.join('.', 'Data.gdb'))
     except IOError: 
         pass # Ignore any errors in writing file

zipws这个函数扔掉,因为你显然不想用它。

看看这个,可能会对你有帮助:http://docs.python.org/library/zipfile.html

1

遍历一个文件夹树的最好方法是使用 os.walk,这个工具可以帮你自动区分文件和文件夹,还能帮你递归地进入子文件夹。

所以:

def zipws(path, zip, filename='Data.gdb'):
  for root, dirs, files in os.walk(path):
    if filename in files:
      zip.write(os.path.join(root, filename),
                os.path.join(os.path.basename(root), filename))
      return

我不太确定你想用来确定 zip.write 的两个参数的逻辑是否完整(从你的代码来看我不是很明白),不过如果不完整,调整起来应该不难。

另外,我不太确定你是否需要最后的 return:这样做的结果是只压缩一个特定名字的文件,而不是压缩树中所有同名的文件(包括它们各自的子文件夹里的)。如果你知道只有一个这样的文件,那就可以保留 return(这样会稍微加快速度)。如果你想要所有这样的文件,而不止一个,就把 return 去掉。

编辑:结果发现,提问者想要的“一个东西”是一个文件夹,而不是文件。在这种情况下,我建议最简单的解决办法是:

def zipws(path, zip, dirname='Data.gdb'):
  for root, dirs, files in os.walk(path):
    if os.path.basename(root) != dirname: continue
    for filename in files:
      zip.write(os.path.join(root, filename),
                os.path.join(dirname, filename))
    return

再次猜测一下,你到底想用什么来作为你的压缩包名称,这一点还是个谜。

撰写回答