Управление прогрессором выполнения инструмента-скрипта

Если инструменты-скрипты запускаются в одном приложении, то вы можете контролировать работу прогрессора. Вы можете настроить вешний вид прогрессора, выбирая индикатор выполнения процесса по умолчанию или пошаговый.

Более подробно о диалоговом окне с индикатором выполнения см. Понятие диалогового окна с индикатором выполнения в инструментах-скриптах

Указанный ниже код демонстрирует возможности применения индикатора выполнения процесса по умолчанию и пошагового индикатора. Скопируйте этот код в свой редактор Python, сохраните его, а затем создайте для него инструмент-скрипт. У инструмента-скрипта будет два параметра типа Длинное целое, как показано в комментариях к коду. Запустите инструмент-скрипт, применяя разные значения параметров (начните с n = 10 и p = 1, затем попробуйте n = 101 и p = 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, сохраните его, а затем создайте для него инструмент-скрипт. Этот инструмент имеет два входных параметра: параметр таблицы и параметр поля. Запустите инструмент-скрипт с разными размерами таблиц, но с такими, которые содержат 10 000 или более строк, и наблюдайте разницу в производительности.

Скрипт выполняет три отдельных цикла, и каждый цикл выбирает все строки в таблице. Эти циклы отличаются с точки зрения того, как они обновляют шкалу хода выполнения. Первый и второй циклы обновляют шкалу хода выполнения большими приростами, а последний цикл увеличивает эту шкалу один раз в каждой строке. Когда вы будете запускать этот инструмент, вы увидите, что для запуска этого последнего цикла требуется больше времени.

Вы можете использовать имеющуюся в данном коде технику для ваших собственных инструментов-скриптов.

'''
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])

Связанные разделы