進行状況ダイアログ ボックスの制御

スクリプト ツールはアプリケーションを共有するので、[進行状況] ダイアログ ボックスを制御できます。デフォルト プログレッサとステップ プログレッサのいずれかを選択することで、[進行状況] ダイアログ ボックスの外観を制御できます。

[進行状況] ダイアログ ボックスの詳細については、「スクリプト ツールの進行状況ダイアログ ボックスの概要」をご参照ください。

次のコードは、デフォルト プログレッサとステップ プログレッサの使用法を示したものです。このコードを Python エディタにコピーし、保存してから、そのスクリプト ツールを作成してください。コードのコメントに説明されているように、このスクリプト ツールには 2 つの Long 整数パラメータがあります。次に、スクリプト ツールを実行し、パラメータに異なる値を設定します(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 = int(arcpy.GetParameterAsText(0))
p = int(arcpy.GetParameterAsText(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 xrange(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 エディタにコピーし、保存してから、そのスクリプト ツールを作成します。このツールには、テーブル パラメータとフィールド パラメータの 2 つの入力があります。スクリプト ツールをさまざまなサイズのテーブルを使用して実行します。必ず 10,000 以上の行を含むテーブルまたはフィーチャクラスを試して、パフォーマンスの違いを調べます(ツールをプロセス内とプロセス外で実行してみて、プロセス内で実行した場合のパフォーマンスの向上を確認することもできます)。

このスクリプトは、3 つのループを実行します。各ループでは、テーブルのすべての行を取得しています。これらのループは、ステップ プログレッサの更新方法が異なります。最初と 2 番目のループは、ステップ プログレッサを大きな増分で更新しています。最後のループは、各行ごとにステップ プログレッサを増加させています。ツールを実行すると、この最後のループの実行に時間がかかることがわかります。

このコードにある手法をスクリプト ツールに利用してください。

'''
Demonstrates a step progressor by looping through records
on a table. Use a table with 10,000 or so rows - smaller tables
just whiz by.
   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])

関連トピック

9/14/2013