for 循环中的嵌套 if 语句
nested if statements within for loops
我有一个关于多重嵌套语句的一般性问题。对于 "complicated nesting"(>3/4 层),什么是更好的方法,尤其是在迭代和使用 if 语句时?
我有很多文件,有的在子目录下,有的在根目录下。我想从许多目录中提取数据集并附加到目标数据集(主数据集)。
for special_directory in directorylist:
for dataset in special_directory:
if dataset in list_of_wanted:
some_code
if it_already_exists:
for feature_class in dataset:
if feature_class in list_of_wanted:
然后我真正进入代码处理的核心。坦率地说,我想不出一种方法来避免这些嵌套的条件语句和循环语句。有什么我想念的吗?我应该使用 "while" 而不是 "for" 吗?
我的实际特定代码有效。它只是不会移动得很快。它迭代 27 个数据库以将每个数据库的内容附加到新的目标数据库。我的 python 已经 运行 36 个小时了,到 4/27 为止。提示?
我在 GIS 堆栈交换中发布了这个,但我的问题真的太笼统了,不属于那里:question and more specific code
有什么建议吗?这方面的最佳做法是什么?这已经是代码的一个子集。这会从另一个脚本生成的列表中的地理数据库中查找数据集和其中的特征 类。第三个脚本查找存储在地理数据库中(即不在数据集中)的要素 类。
ds_wanted = ["Hydrography"]
fc_wanted = ["NHDArea","NHDFlowline","NHDLine","NHDWaterbody"]
for item in gdblist:
env.workspace = item
for dsC in arcpy.ListDatasets():
if dsC in ds_wanted:
secondFD = os.path.join(gdb,dsC)
if arcpy.Exists(secondFD):
print (secondFD + " exists, not copying".format(dsC))
for fcC in arcpy.ListFeatureClasses(feature_dataset=dsC):
if fcC in fc_wanted:
secondFC2 = os.path.join(gdb,dsC, fcC)
if arcpy.Exists(secondFC2):
targetd2 = os.path.join(gdb,dsC,fcC)
# Create FieldMappings object and load the target dataset
#
print("Now begin field mapping!")
print("from {} to {}").format(item, gdb)
print("The target is " + targetd2)
fieldmappings = arcpy.FieldMappings()
fieldmappings.addTable(targetd2)
# Loop through each field in the input dataset
#
inputfields = [field.name for field in arcpy.ListFields(fcC) if not field.required]
for inputfield in inputfields:
# Iterate through each FieldMap in the FieldMappings
for i in range(fieldmappings.fieldCount):
fieldmap = fieldmappings.getFieldMap(i)
# If the field name from the target dataset matches to a validated input field name
if fieldmap.getInputFieldName(0) == inputfield.replace(" ", "_"):
# Add the input field to the FieldMap and replace the old FieldMap with the new
fieldmap.addInputField(fcC, inputfield)
fieldmappings.replaceFieldMap(i, fieldmap)
break
# Perform the Append
#
print("Appending stuff...")
arcpy.management.Append(fcC, targetd2, "NO_TEST", fieldmappings)
else:
arcpy.Copy_management(fcC, secondFC2)
print("Copied " +fcC+ "into " +gdb)
else:
pass
else:
arcpy.Copy_management(dsC,secondFD) # Copies feature class from first gdb to second gdb
print "Copied "+ dsC +" into " + gdb
else:
pass
print "{} does not need to be copied to DGDB".format(dsC)
print("Done with datasets and the feature classes within them.")
好像真的被抓到了arcpy.management.Append
我对这个功能有一些公平的经验,尽管这是一个比典型的 table 模式更大的模式(更多记录,更多字段),但单个追加需要 12 个多小时。以我原来的问题为基础,这可能是因为它嵌套得太深了吗?还是情况并非如此,数据只是需要时间来处理?
对您的问题的一些好评。我在多处理方面的经验有限,但是让所有计算机内核正常工作通常会加快速度。如果您的四核处理器在脚本执行期间仅 运行ning 大约 25%,那么您可能会受益。你只需要小心你如何应用它,以防一件事总是在另一件事之前发生。如果您使用的是文件地理数据库而不是企业级 gdb,那么您的瓶颈可能出在磁盘上。如果 gdb 是远程的,网络速度可能是问题所在。无论哪种方式,多处理都无济于事。 Windows 上的资源监视器会让您大致了解 processor/disk/RAM/network 的使用量。
我刚刚使用了一个使用 rpy2 和数据的类似脚本 from/to PostGIS。 运行 仍然需要大约 30 个小时,但这比 100 个小时要好得多。我还没有在 Arc 中使用多处理(我主要从事开源工作),但知道有人使用过。
多处理的一个非常简单的实现:
from multiprocessing import Pool
def multi_run_wrapper(gdblist):
"""Helper function to unpack argument lists during multiprocessing.
Modified from: """
return gdb_append(*gdblist) # the * unpacks the list
def gdb_append(gdb_id):
...
# script starts here #
gdblist = [......]
if __name__ == '__main__':
p = Pool()
p.map(multi_run_wrapper, gdblist)
print("Script Complete")
通常您会加入池的结果,但由于您使用它来执行任务,我不确定是否有必要这样做。其他人可能会插话什么是最佳实践。
我有一个关于多重嵌套语句的一般性问题。对于 "complicated nesting"(>3/4 层),什么是更好的方法,尤其是在迭代和使用 if 语句时?
我有很多文件,有的在子目录下,有的在根目录下。我想从许多目录中提取数据集并附加到目标数据集(主数据集)。
for special_directory in directorylist:
for dataset in special_directory:
if dataset in list_of_wanted:
some_code
if it_already_exists:
for feature_class in dataset:
if feature_class in list_of_wanted:
然后我真正进入代码处理的核心。坦率地说,我想不出一种方法来避免这些嵌套的条件语句和循环语句。有什么我想念的吗?我应该使用 "while" 而不是 "for" 吗?
我的实际特定代码有效。它只是不会移动得很快。它迭代 27 个数据库以将每个数据库的内容附加到新的目标数据库。我的 python 已经 运行 36 个小时了,到 4/27 为止。提示?
我在 GIS 堆栈交换中发布了这个,但我的问题真的太笼统了,不属于那里:question and more specific code
有什么建议吗?这方面的最佳做法是什么?这已经是代码的一个子集。这会从另一个脚本生成的列表中的地理数据库中查找数据集和其中的特征 类。第三个脚本查找存储在地理数据库中(即不在数据集中)的要素 类。
ds_wanted = ["Hydrography"]
fc_wanted = ["NHDArea","NHDFlowline","NHDLine","NHDWaterbody"]
for item in gdblist:
env.workspace = item
for dsC in arcpy.ListDatasets():
if dsC in ds_wanted:
secondFD = os.path.join(gdb,dsC)
if arcpy.Exists(secondFD):
print (secondFD + " exists, not copying".format(dsC))
for fcC in arcpy.ListFeatureClasses(feature_dataset=dsC):
if fcC in fc_wanted:
secondFC2 = os.path.join(gdb,dsC, fcC)
if arcpy.Exists(secondFC2):
targetd2 = os.path.join(gdb,dsC,fcC)
# Create FieldMappings object and load the target dataset
#
print("Now begin field mapping!")
print("from {} to {}").format(item, gdb)
print("The target is " + targetd2)
fieldmappings = arcpy.FieldMappings()
fieldmappings.addTable(targetd2)
# Loop through each field in the input dataset
#
inputfields = [field.name for field in arcpy.ListFields(fcC) if not field.required]
for inputfield in inputfields:
# Iterate through each FieldMap in the FieldMappings
for i in range(fieldmappings.fieldCount):
fieldmap = fieldmappings.getFieldMap(i)
# If the field name from the target dataset matches to a validated input field name
if fieldmap.getInputFieldName(0) == inputfield.replace(" ", "_"):
# Add the input field to the FieldMap and replace the old FieldMap with the new
fieldmap.addInputField(fcC, inputfield)
fieldmappings.replaceFieldMap(i, fieldmap)
break
# Perform the Append
#
print("Appending stuff...")
arcpy.management.Append(fcC, targetd2, "NO_TEST", fieldmappings)
else:
arcpy.Copy_management(fcC, secondFC2)
print("Copied " +fcC+ "into " +gdb)
else:
pass
else:
arcpy.Copy_management(dsC,secondFD) # Copies feature class from first gdb to second gdb
print "Copied "+ dsC +" into " + gdb
else:
pass
print "{} does not need to be copied to DGDB".format(dsC)
print("Done with datasets and the feature classes within them.")
好像真的被抓到了arcpy.management.Append 我对这个功能有一些公平的经验,尽管这是一个比典型的 table 模式更大的模式(更多记录,更多字段),但单个追加需要 12 个多小时。以我原来的问题为基础,这可能是因为它嵌套得太深了吗?还是情况并非如此,数据只是需要时间来处理?
对您的问题的一些好评。我在多处理方面的经验有限,但是让所有计算机内核正常工作通常会加快速度。如果您的四核处理器在脚本执行期间仅 运行ning 大约 25%,那么您可能会受益。你只需要小心你如何应用它,以防一件事总是在另一件事之前发生。如果您使用的是文件地理数据库而不是企业级 gdb,那么您的瓶颈可能出在磁盘上。如果 gdb 是远程的,网络速度可能是问题所在。无论哪种方式,多处理都无济于事。 Windows 上的资源监视器会让您大致了解 processor/disk/RAM/network 的使用量。
我刚刚使用了一个使用 rpy2 和数据的类似脚本 from/to PostGIS。 运行 仍然需要大约 30 个小时,但这比 100 个小时要好得多。我还没有在 Arc 中使用多处理(我主要从事开源工作),但知道有人使用过。
多处理的一个非常简单的实现:
from multiprocessing import Pool
def multi_run_wrapper(gdblist):
"""Helper function to unpack argument lists during multiprocessing.
Modified from: """
return gdb_append(*gdblist) # the * unpacks the list
def gdb_append(gdb_id):
...
# script starts here #
gdblist = [......]
if __name__ == '__main__':
p = Pool()
p.map(multi_run_wrapper, gdblist)
print("Script Complete")
通常您会加入池的结果,但由于您使用它来执行任务,我不确定是否有必要这样做。其他人可能会插话什么是最佳实践。