控制脚本工具的进度条

由于脚本工具共享了应用程序,因此您可以控制进度条。您可以通过选择默认进度条或步骤进度条来控制进度条的外观。

要了解有关进度对话框的详细信息,请参阅了解脚本工具中的进度对话框

以下代码说明了对默认进度条和步骤进度条的充分使用。将此代码复制到 Python 编辑器中,进行保存,然后为其创建脚本工具。脚本工具具有两个长整型参数,如代码注释中所述。然后运行脚本工具,同时为参数提供不同值(以 n = 10p = 1 开始,然后尝试 n = 101p = 3)。

'''
Demonstration script showing examples of using the progressor
 Parameters:
   n - number to count to (a good first choice is 10)
   p - interval to count by (a good first choice is 1)
The various time.sleep() calls are just to slow the dialog down
so you can view messages and progressor labels.
'''

import arcpy
import time

n = arcpy.GetParameter(0)
p = arcpy.GetParameter(1)

readTime = 2.5  # Pause to read what's written on dialog
loopTime = 0.3  # Loop iteration delay

arcpy.AddMessage("Running demo with: {0} by {1}\n".format(n, p))

# Start by showing the default progress dialog, where the
#  progress bar goes back and forth. Note how the progress label
#  mimics working through some "phases", or chunks of work that
#  a script may perform.
#
arcpy.SetProgressor("default", "This is the default progressor")
time.sleep(readTime)

for i in range(1, 4):
    arcpy.SetProgressorLabel("Working on 'phase' {0}".format(i))
    arcpy.AddMessage("Messages for phase {0}".format(i))
    time.sleep(readTime)

# Setup the progressor with its initial label, min, max, and interval
#
arcpy.SetProgressor("step",
                    "Step progressor: Counting from 0 to {0}".format(n),
                    0, n, p)
time.sleep(readTime)

# Loop issuing a new label when the increment is divisible by the
#  value of countBy (p). The "%" is python's modulus operator - we
#  only update the position every p'th iteration
#
for i in range(n):
    if (i % p) == 0:
        arcpy.SetProgressorLabel("Iteration: {0}".format(i))
        arcpy.SetProgressorPosition(i)
        time.sleep(loopTime)

# Update the remainder that may be left over due to modulus operation
#
arcpy.SetProgressorLabel("Iteration: {0}".format(i + 1))
arcpy.SetProgressorPosition(i + 1)

arcpy.AddMessage("Done counting up\n")
time.sleep(readTime)

# Just for fun, make the progressor go backwards.
#
arcpy.SetProgressor("default", "Default progressor: Now we'll do a countdown")
time.sleep(readTime)
arcpy.AddMessage("Here comes the countdown...")
arcpy.SetProgressor("step",
                    "Step progressor: Counting backwards from {0}".format(n),
                    0, n, p)
time.sleep(readTime)
arcpy.AddMessage("Counting down now...\n")

for i in range(n, 0, -1):
    if (i % p) == 0:
        arcpy.SetProgressorLabel("Iteration: {0}".format(i))
        arcpy.SetProgressorPosition(i)
        time.sleep(loopTime)

# Update for remainder
#
arcpy.SetProgressorLabel("Iteration: {0}".format(i - 1))
arcpy.SetProgressorPosition(i - 1)
time.sleep(readTime)
arcpy.AddMessage("All done")
arcpy.ResetProgressor()

最大值可能很大时选择一个合适的增量

编写迭代次数未知的脚本并不少见。例如,脚本可以使用 SearchCursor 迭代表中的所有行,而您事先并不知道有多少行,也就是说您的脚本可用于迭代从几千行到数百万行的任意大小的表。为大型表中的每行增大步长进度条会出现性能瓶颈问题,最好防止出现此类性能瓶颈。

要演示和评估步长进度条的性能问题,请将下面的代码复制到 Python 编辑器中,然后对其进行保存,之后为其创建一个脚本工具。该工具有两个输入:表参数和字段参数。以不同表大小运行该脚本工具,但一定要尝试使用包含 10000 行或更多行的表或要素类来查看性能差异。

该脚本执行三个独立的循环,每个循环都提取表中的所有行。各个循环在更新步长进度条的方式上有所不同。第一个和第二个循环以较大的增量更新步长进度条,最后一个循环每行增大一次步长进度条。运行该工具时,您会看到最后一个循环运行时间较长。

最好对该脚本工具使用此代码提供的技术。

'''
Demonstrates a step progressor by looping through records
on a table. Use a table with 10,000 or so rows - smaller tables
will finish too quickly to assess.
   1 = table name
   2 = field on the table
'''

import arcpy
import time
import math

try:
    inTable = arcpy.GetParameterAsText(0)
    inField = arcpy.GetParameterAsText(1)

    # Determine number of records in table
    #
    record_count = int(arcpy.GetCount_management(inTable).getOutput(0))
    if record_count == 0:
        raise ValueError("{0} has no records to count".format(inTable))

    arcpy.AddMessage("Number of rows = {0}\n".format(record_count))

    # Method 1: Calculate and use a suitable base 10 increment
    # ===================================

    p = int(math.log10(record_count))
    if not p:
        p = 1
    increment = int(math.pow(10, p - 1))

    arcpy.SetProgressor(
        "step", "Incrementing by {0} on {1}".format(increment, inTable),
        0, record_count, increment)

    beginTime = time.clock()
    with arcpy.da.SearchCursor(inTable, [inField]) as cursor:
        for i, row in enumerate(cursor, 0):
            if (i % increment) == 0:
                arcpy.SetProgressorPosition(i)
            fieldValue = row[0]

    arcpy.SetProgressorPosition(i)
    arcpy.AddMessage("Method 1")
    arcpy.AddMessage("\tIncrement = {0}".format(increment))
    arcpy.AddMessage("\tElapsed time: {0}\n".format(time.clock() - beginTime))

    # Method 2: let's just move in 10 percent increments
    # ===================================
    increment = int(record_count / 10.0)
    arcpy.SetProgressor(
        "step", "Incrementing by {0} on {1}".format(increment, inTable),
        0, record_count, increment)

    beginTime = time.clock()
    with arcpy.da.SearchCursor(inTable, [inField]) as cursor:
        for i, row in enumerate(cursor, 0):
            if (i % increment) == 0:
                arcpy.SetProgressorPosition(i)
            fieldValue = row[0]

    arcpy.SetProgressorPosition(i)
    arcpy.AddMessage("Method 2")
    arcpy.AddMessage("\tIncrement = {0}".format(increment))
    arcpy.AddMessage("\tElapsed time: {0}\n".format(time.clock() - beginTime))

    # Method 3: use increment of 1
    # ===================================
    increment = 1
    arcpy.SetProgressor("step",
                        "Incrementing by 1 on {0}".format(inTable),
                        0, record_count, increment)

    beginTime = time.clock()
    with arcpy.da.SearchCursor(inTable, [inField]) as cursor:
        for row in cursor:
            arcpy.SetProgressorPosition()
            fieldValue = row[0]

    arcpy.SetProgressorPosition(record_count)
    arcpy.ResetProgressor()
    arcpy.AddMessage("Method 3")
    arcpy.AddMessage("\tIncrement = {0}".format(increment))
    arcpy.AddMessage("\tElapsed time: {0}\n".format(time.clock() - beginTime))

    arcpy.AddMessage("Pausing for a moment to allow viewing...")
    time.sleep(2.0)  # Allow viewing of the finished progressor

except Exception as e:
    arcpy.AddError(e[0])

相关主题