Python でのジオデータベースの操作
テーブル名の検証
ジオデータベースは、さまざまなリレーショナル データベース管理システム(RDBMS)を使用して、ジオデータベースを構成するテーブルを管理します。ジオデータベース内のすべてのテーブルには一意な名前が付いていなければならないため、ジオデータベース内にデータを作成する際には、テーブル名が一意であるかどうかを確認するためのメカニズムが不可欠です。新しいテーブル名が一意であることの確認は、新しい出力名が一意であることをスクリプトが保証していない場合に、データが誤って上書きされないようにするために不可欠です。
注意:Exists() 関数を使用すれば、特定のワークスペースでテーブル名が一意であるかどうかを確認できます。
ValidateTableName() 関数を使用すると、指定した名前が特定のワークスペースに対して有効であり、一意であるかどうかをスクリプトで判定することができます。ValidateTableName() 関数は、指定のワークスペースに対して指定の名前が一意であるかどうかの判定は行いません。この関数は、そのワークスペースに対して有効なテーブル名のみを返します。
|
関数 |
説明 |
|---|---|
|
ValidateTableName(name, {workspace}) |
テーブル名とワークスペース パスを受け入れ、そのワークスペースに対して有効なテーブル名を返します。 |
ワークスペースをパラメータとして指定すると、ArcPy は既存のすべてのテーブル名を検査し、出力ワークスペースに命名上の制限があるかどうかを判別できます。出力ワークスペースが RDBMS である場合は、テーブル名に使用できない予約語が存在する可能性があります。また、テーブル名やフィールド名に使用できない無効な文字が存在する場合もあります。無効な文字はすべて下線(_)に置き換えられます。ValidateTableName() は、有効なテーブル名を表す文字列を返します。入力として指定した名前が有効であれば、同じ名前が返されます。次の例は、[フィーチャのコピー(Copy Features)] ツールによって作成される新しい出力フィーチャクラスの名前が、どのジオデータベースでも有効な一意の名前であることを保証します。
# Move all shapefiles from a folder into a geodatabase
#
import arcpy
from arcpy import env
# Set the workspace. List all of the shapefiles
#
env.workspace = "D:/St_Johns"
fcs = arcpy.ListFeatureClasses("*")
# Set the workspace to SDE for ValidateTableName
#
env.workspace = "Database Connections/Bluestar.sde"
# For each feature class name
#
for fc in fcs:
# Validate the output name so it is valid
#
outfc = arcpy.ValidateTableName(fc)
# Copy the features from the workspace to a geodatabase
#
arcpy.CopyFeatures_management(fc, outfc)
フィールド名の検証
各データベースは、テーブルのフィールド名に関して命名上の制限を設けていることがあります。フィーチャクラスやリレーションシップ クラスといったオブジェクトは、RDBMS にテーブルとして格納されるため、これらの制限の影響はテーブル単体だけでなく広範囲にわたります。こうした制限があるかどうかは、データベース システムによって異なります。このため、スクリプトで新しいフィールド名をすべてチェックして、ツールが実行中に失敗しないようにする必要があります。
|
関数 |
説明 |
|---|---|
|
ValidateFieldName(name, {workspace}) |
文字列(フィールド名)とワークスペース パスを受け入れ、出力ジオデータベースの命名上の制限に基づいて有効なフィールド名を返します。 |
次の例では、ValidateFieldName 関数を使用して、どのような入力名が指定された場合でもフィールドが確実に追加されるようにします。
# Create a new numeric field containing the ratio of polygon area to
# polygon perimeter. Two arguments, a feature class and field name,
# are expected.
# Define a pair of simple exceptions for error handling
#
class ShapeError(Exception):
pass
class FieldError(Exception):
pass
import arcpy
import os
try:
# Get the input feature class and make sure it contains polygons
#
input = arcpy.GetParameterAsText(0)
desc = arcpy.Describe(input)
if desc.shapeType.lower() != "polygon":
raise ShapeError
# Get the new field name and validate it
#
fieldname = arcpy.GetParameterAsText(1)
fieldname = arcpy.ValidateFieldName(fieldname, os.path.dirname(input))
# Make sure shape_length and shape_area fields exist
#
if len(arcpy.ListFields(input,"Shape_area")) > 0 and \
len(arcpy.ListFields(input,"Shape_length")) > 0:
# Add the new field and calculate the value
#
arcpy.AddField_management(input, fieldname, "double")
arcpy.CalculateField_management(input,fieldname,
"[Shape_area] / [Shape_length]")
else:
raise FieldError
except ShapeError:
print "Input does not contain polygons"
except FieldError:
print "Input does not contain shape area and length fields"
except:
print arcpy.GetMessages(2)
スクリプトからフィーチャクラスやテーブルなどのデータセットを更新する場合は、データセットがロックされる状況を回避するように注意してください。パーソナル ジオデータベースやファイル ジオデータベースを ArcCatalog でオープンした場合は、そのジオデータベースが選択解除され、フォルダがリフレッシュされるか ArcCatalog がクローズされるまで、ジオデータベースの内容をスクリプトから更新することはできません。このことはスクリプト ツールにも当てはまります。
テーブル名とフィールド名の分解
スクリプトでは、ParseTableName() 関数と ParseFieldName() 関数を使用して、データセットまたはテーブルの列の完全修飾名を個々の要素(データベース、所有者、テーブル、列)に分解します。RDBMS に依存しないことを必要とするスクリプトでは、ピリオド(.)が完全修飾データセット名の構成要素の区切り文字であることを前提にしてはなりません。ArcGIS アプリケーションは常に完全修飾名を使用します。このため、スクリプトがスクリプト ツールのソースとして使用され、たとえばユーザ名やデータベース名を取り除いたフィーチャクラスの名前を判別する必要がある場合は、フィーチャクラス名を解析する必要があります。次のスクリプト例では、特定のユーザ名があるかどうか入力フィーチャクラスを検査します。このスクリプトは、Python の解析関数を使って修飾名を分解することもできますが、その場合は特定の構文を前提とすることになり、別のタイプのデータベースが使用される場合には構文が異なる可能性があります。ParseTableName() は、カンマで区切られたデータベース名、所有者名、およびテーブル名を含む単一の文字列を返します。ParseFieldName() はテーブル名とフィールド名を返し、これらもカンマで区切られています。これらの関数は常に同じ形式の文字列を返すので、スクリプトは返された文字列を確実に解析することができます。Python には、文字列を操作するためのネイティブ メソッドがいくつか備わっています。次の例では、split メソッドを使用して、区切り文字としてカンマを使用する Python リストを作成します。
|
関数 |
説明 |
|---|---|
|
ParseFieldName(name, {workspace}) |
完全修飾フィールド名を解析して、ワークスペースに応じた構成要素(データベース、所有者名、テーブル名、フィールド名)に分解します。 |
|
ParseTableName(name, {workspace}) |
テーブル名を解析して、ワークスペースに応じた構成要素(データベース、所有者、テーブル)に分解します。 |
# Append input feature class to another feature class and update field
#
import arcpy
from arcpy import env
import sys
# Get the name of the input feature class and parse it.
#
env.workspace = os.path.dirname(arcpy.GetParameterAsText(0))
# Split ParseTableName's returned value to determine database, owner, and
# featureclass
#
fullname = arcpy.ParseTableName(os.path.basename(arcpy.GetParameterAsText(0)))
database, owner, featureclass = fullname.split(",")
# Validate the name of the feature class that will be appended to and set
# the workspace using the administrator's connection
#
env.workspace = "Database Connections/Trans_admin.sde"
appendFC = arcpy.ValidateTableName("common", "roads")
try:
if owner == "TJohnson":
arcpy.CalculateField_management(fullname, "AppendedBy", owner)
arcpy.Append_management(fullname, appendFC)
elif owner == "RSmith":
arcpy.CalculateField_management(fullname, "AppendedBy", owner)
arcpy.Append_management(fullname, appendFC)
else:
arcpy.AddError("Unknown user of input feature class")
except:
arcpy.AddError(arcpy.GetMessages(2))
Python リストは、文字列や数値など、任意のタイプのオブジェクトからなる順序付きのコレクションです。リストは 0 から始まり、リストの内容の順序が分かっていれば、リストを使用して値の配列を効率的に処理できます。
スクリプト ツールのソースとして使用されるスクリプトは、入力引数値についていくつかのことを前提にして処理できます。データのパスは、ジオプロセシング フレームワークによって常に完全に修飾されます。ただし、ArcGIS アプリケーションの外部で実行される可能性があるスクリプトでは、このことを前提にしてはなりません。