为什么Python程序在使用函数时执行速度变慢?

为什么Python程序在使用函数时执行速度变慢?,python,Python,所以我有一个相当普遍的问题,我希望得到一些帮助。我编写了一个Python程序,该程序在州一级为所有不同的县运行并自动化工作流。整个项目是为学校的研究而创建的,而不是实际的国家工作。无论如何,我有两个设计如下所示。第一个是更新版本。运行大约需要40分钟。第二个设计展示了原作。请注意,它不是一个结构良好的设计。但是,运行整个程序大约需要五分钟。有人能解释一下为什么两者之间存在如此大的差异吗?更新后的版本仍然是理想的,因为它更易于重用(可以运行和获取url中的任何数据集)并且易于理解。此外,40分钟完

所以我有一个相当普遍的问题,我希望得到一些帮助。我编写了一个Python程序,该程序在州一级为所有不同的县运行并自动化工作流。整个项目是为学校的研究而创建的,而不是实际的国家工作。无论如何,我有两个设计如下所示。第一个是更新版本。运行大约需要40分钟。第二个设计展示了原作。请注意,它不是一个结构良好的设计。但是,运行整个程序大约需要五分钟。有人能解释一下为什么两者之间存在如此大的差异吗?更新后的版本仍然是理想的,因为它更易于重用(可以运行和获取url中的任何数据集)并且易于理解。此外,40分钟完成大约100个工作流程仍然是一个优势。此外,这项工作仍在进行中。代码中仍然需要解决一些小问题,但它仍然是一个非常酷的程序

更新设计

import os, sys, urllib2, urllib, zipfile, arcpy
from arcpy import env

path = os.getcwd()

def pickData():
    myCount = 1
    path1 = 'path2URL'
    response = urllib2.urlopen(path1)
    print "Enter the name of the files you need"
    numZips = raw_input()
    numZips2 = numZips.split(",")
    myResponse(myCount, path1, response, numZips2)

def myResponse(myCount, path1, response, numZips2):
    myPath = os.getcwd()
    for each in response:
        eachNew = each.split("  ")
        eachCounty = eachNew[9].strip("\n").strip("\r")
        try:
            myCountyDir = os.mkdir(os.path.expanduser(myPath+ "\\counties" + "\\" + eachCounty))
        except:
            pass
        myRetrieveDir = myPath+"\\counties" + "\\" + eachCounty
        os.chdir(myRetrieveDir)
        myCount+=1
        response1 = urllib2.urlopen(path1 + eachNew[9])
        for all1 in response1:
            allNew = all1.split(",")
            allFinal = allNew[0].split(" ")
            allFinal1 = allFinal[len(allFinal)-1].strip(" ").strip("\n").strip("\r")
            numZipsIter = 0
            path8 = path1 + eachNew[9][0:len(eachNew[9])-2] +"/"+ allFinal1
            downZip = eachNew[9][0:len(eachNew[9])-2]+".zip"
            while(numZipsIter <len(numZips2)):
                if (numZips2[numZipsIter][0:3].strip(" ") == "NWI") and ("remap" not in allFinal1):
                    numZips2New = numZips2[numZipsIter].split("_")
                    if (numZips2New[0].strip(" ") in allFinal1 and numZips2New[1] != "remap" and numZips2New[2].strip(" ") in allFinal1) and (allFinal1[-3:]=="ZIP" or allFinal1[-3:]=="zip"):
                        urllib.urlretrieve (path8,  allFinal1)
                        zip1 = zipfile.ZipFile(myRetrieveDir +"\\" + allFinal1)
                        zip1.extractall(myRetrieveDir)
                #maybe just have numzips2 (raw input) as the values before the county number
                #numZips2[numZipsIter][0:-7].strip(" ") in allFinal1 or numZips2[numZipsIter][0:-7].strip(" ").lower() in allFinal1) and (allFinal1[-3:]=="ZIP" or allFinal1[-3:]=="zip"
                elif (numZips2[numZipsIter].strip(" ") in allFinal1 or numZips2[numZipsIter].strip(" ").lower() in allFinal1) and (allFinal1[-3:]=="ZIP" or allFinal1[-3:]=="zip"):
                    urllib.urlretrieve (path8,  allFinal1)
                    zip1 = zipfile.ZipFile(myRetrieveDir +"\\" + allFinal1)
                    zip1.extractall(myRetrieveDir)
                numZipsIter+=1



pickData()

#client picks shapefiles to add to map
#section for geoprocessing operations




# get the data frames



#add new data frame, title
#check spaces in ftp crawler



os.chdir(path)
env.workspace = path+ "\\symbology\\"
zp1 = os.listdir(path + "\\counties\\")

def myGeoprocessing(layer1, layer2):
    #the code in this function is used for geoprocessing operations
    #it returns whatever output is generated from the tools used in the map
    try:
        arcpy.Clip_analysis(path + "\\symbology\\Stream_order.shp", layer1, path + "\\counties\\" + layer2 + "\\Streams.shp")
    except:
        pass
    streams = arcpy.mapping.Layer(path + "\\counties\\" + layer2 + "\\Streams.shp")
    arcpy.ApplySymbologyFromLayer_management(streams, path+ '\\symbology\\streams.lyr')
    return streams

def makeMap():
    #original wetlands layers need to be entered as NWI_line or NWI_poly
    print "Enter the layer or layers you wish to include in the map"
    myInput = raw_input();
    counter1 = 1
    for each in zp1:
        print each
        print path
        zp2 = os.listdir(path + "\\counties\\" + each)
        for eachNew in zp2:
            #print eachNew
            if (eachNew[-4:] == ".shp") and ((myInput in eachNew[0:-7] or myInput.lower() in eachNew[0:-7])or((eachNew[8:12] == "poly" or eachNew[8:12]=='line') and eachNew[8:12] in myInput)):
                print eachNew[0:-7]
                theMap = arcpy.mapping.MapDocument(path +'\\map.mxd')
                df1 = arcpy.mapping.ListDataFrames(theMap,"*")[0]
                #this is where we add our layers
                layer1 = arcpy.mapping.Layer(path + "\\counties\\" + each + "\\" + eachNew)
                if(eachNew[7:11] == "poly" or eachNew[7:11] =="line"):
                    arcpy.ApplySymbologyFromLayer_management(layer1, path + '\\symbology\\' +myInput+'.lyr')
                else:
                    arcpy.ApplySymbologyFromLayer_management(layer1, path + '\\symbology\\' +eachNew[0:-7]+'.lyr')

                # Assign legend variable for map
                legend = arcpy.mapping.ListLayoutElements(theMap, "LEGEND_ELEMENT", "Legend")[0]
                # add wetland layer to map
                legend.autoAdd = True
                try:
                    arcpy.mapping.AddLayer(df1, layer1,"AUTO_ARRANGE")
                    #geoprocessing steps
                    streams = myGeoprocessing(layer1, each)
                    # more geoprocessing options, add the layers to map and assign if they should appear in legend
                    legend.autoAdd = True
                    arcpy.mapping.AddLayer(df1, streams,"TOP")

                    df1.extent = layer1.getExtent(True)

                    arcpy.mapping.ExportToJPEG(theMap, path + "\\counties\\" + each + "\\map.jpg")
                    # Save map document to path
                    theMap.saveACopy(path + "\\counties\\" + each + "\\map.mxd")
                    del theMap

                    print "done with map " + str(counter1)
                except:
                    print "issue with map or already exists"
                counter1+=1

makeMap() 

请参阅本指南:

让我引述:

Python中的函数调用开销相对较高,特别是与内置函数的执行速度相比。这强烈建议,在适当的情况下,函数应该处理数据聚合

因此,有效地说,这意味着,不要把某些东西作为一个函数来计算,这个函数将被调用数十万次

在Python中,函数不会内联,调用它们也不便宜。如果有疑问,请使用探查器了解每个函数调用了多少次,以及平均需要多长时间。然后优化

您还可以尝试一下PyPy,因为它们内置了某些优化。在某些情况下,减少函数调用开销似乎是其中之一:


函数调用增加了开销。在任何语言中,不仅仅是在python中。
import os, sys, urllib2, urllib, zipfile, arcpy
from arcpy import env

response = urllib2.urlopen('path2URL')
path1 = 'path2URL'
myCount = 1
for each in response:
    eachNew = each.split("  ")
    myCount+=1
    response1 = urllib2.urlopen(path1 + eachNew[9])
    for all1 in response1:
        #print all1
        allNew = all1.split(",")
        allFinal = allNew[0].split(" ")
        allFinal1 = allFinal[len(allFinal)-1].strip(" ")
        if allFinal1[-10:-2] == "poly.ZIP":
            response2 = urllib2.urlopen('path2URL')
            zipcontent= response2.readlines()
            path8 = 'path2URL'+ eachNew[9][0:len(eachNew[9])-2] +"/"+ allFinal1[0:len(allFinal1)-2]
            downZip = str(eachNew[9][0:len(eachNew[9])-2])+ ".zip"
            urllib.urlretrieve (path8,  downZip)






# Set the path to the directory where your zipped folders reside
zipfilepath = 'F:\Misc\presentation'
# Set the path to where you want the extracted data to reside
extractiondir = 'F:\Misc\presentation\counties'
# List all data in the main directory
zp1 = os.listdir(zipfilepath)
# Creates a loop which gives use each zipped folder automatically
# Concatinates zipped folder to original directory in variable done
for each in zp1:
    print each[-4:]
    if each[-4:] == ".zip":
        done = zipfilepath + "\\" + each
        zip1 = zipfile.ZipFile(done)
        extractiondir1 = extractiondir + "\\" + each[:-4]
        zip1.extractall(extractiondir1)



path = os.getcwd()
counter1 = 1

# get the data frames


# Create new layer for all files to be added to map document


env.workspace = "E:\\Misc\\presentation\\symbology\\"
zp1 = os.listdir(path + "\\counties\\")
for each in zp1:
    zp2 = os.listdir(path + "\\counties\\" + each)
    for eachNew in zp2:
        if eachNew[-4:] == ".shp":
            wetlandMap = arcpy.mapping.MapDocument('E:\\Misc\\presentation\\wetland.mxd')
            df1 = arcpy.mapping.ListDataFrames(wetlandMap,"*")[0]
            #print eachNew[-4:]
            wetland = arcpy.mapping.Layer(path + "\\counties\\" + each + "\\" + eachNew)
            #arcpy.Clip_analysis(path + "\\symbology\\Stream_order.shp", wetland, path + "\\counties\\" + each + "\\Streams.shp")
            streams = arcpy.mapping.Layer(path + "\\symbology\\Stream_order.shp")
            arcpy.ApplySymbologyFromLayer_management(wetland, path + '\\symbology\\wetland.lyr')
            arcpy.ApplySymbologyFromLayer_management(streams, path+ '\\symbology\\streams.lyr')
            # Assign legend variable for map
            legend = arcpy.mapping.ListLayoutElements(wetlandMap, "LEGEND_ELEMENT", "Legend")[0]
            # add the layers to map and assign if they should appear in legend
            legend.autoAdd = True
            arcpy.mapping.AddLayer(df1, streams,"TOP")
            legend.autoAdd = True
            arcpy.mapping.AddLayer(df1, wetland,"AUTO_ARRANGE")

            df1.extent = wetland.getExtent(True)
            # Export the map to a pdf
            arcpy.mapping.ExportToJPEG(wetlandMap, path + "\\counties\\" + each + "\\wetland.jpg")
            # Save map document to path
            wetlandMap.saveACopy(path + "\\counties\\" + each + "\\wetland.mxd")
            del wetlandMap

            print "done with map " + str(counter1)
            counter1+=1