Python スクリプトのパッケージ化

詳細:

コンピューター上で正常に動作する Python スクリプト ツールの大部分は、パッケージ化して別のコンピューター上で解凍したときに、正常に実行することができます。スクリプトを変更する必要はまったくありません。ただし、問題が発生した場合は、その原因として、スクリプトがハードコーディングされたデータ パスを使用しているか、開発した Python モジュールをインポートするための import ステートメントを使用していることが考えられます。このようなエラーが発生した場合、このトピックは、次の内容を詳しく説明しているため、解決に役立ちます。

  1. スクリプト内のハードコーディングされたパスを含むデータがどのように検索されてパッケージに含められるか。
  2. インポートされるモジュールがどのように検索されてパッケージに含められるか。
  3. ツールの整合チェック コードがどのようにパッケージ化されるか。
  4. サードパーティ ライブラリがどのようにパッケージ化されるか。

スクリプト内のデータを検出する方法

パッケージまたはサービスのどちらでも結果を共有し、その結果がスクリプト ツールを参照している場合は必ず、スクリプトで使用されているデータを検出するためにスクリプト ツールがスキャンされます。データ パスが検出された場合、そのパスはパッケージに含まれる一時フォルダーに統合されます。

スクリプトがスキャンされると、Python 変数で使用されるまたは関数への引数として使用されるそれぞれの引用符 (一重または二重のいずれか) で囲まれた文字列がテストされ、存在するデータへのパスであるかどうかが確認されます。この場合のデータとは次のものを意味します。

  • マップ レイヤー
  • フォルダー
  • ファイル
  • ジオデータセット (フィーチャクラス、シェープファイル、ジオデータベース、レイヤー ファイルなど)

ここでは、ジオプロセシング ツールへの入力としてまたは他の Python モジュールを参照するパスとして使用されるデータのみを対象とします。出力データも統合されます。

スクリプトに引用符で囲まれた文字列が発見されると、データの存在を確認する以下のようなテストが実行されます。

  1. 文字列はマップ レイヤーを参照するか?
  2. 文字列にデータへの絶対パス (e:\Warehousing\ToolData\SanFrancisco.gdb\streets など) が含まれているか?
  3. 文字列はスクリプトの場所からの相対で発見できるデータを参照するか? スクリプトの場所は次のように定義されます。
    • スクリプトが格納されているフォルダー。
    • スクリプトがツールボックスに埋め込まれている場合、その場所はツールボックスが格納されているフォルダーになります。
    • スクリプトが Python ツールボックスに含まれている場合、その場所は Python ツールボックスが格納されているフォルダーになります。

これらのテストは、順次実行されます。テストに合格し、データが存在することがわかると、そのデータが統合されます。

メモ:

フォルダーが統合される場合、フォルダー内のファイルとジオデータセットのみがコピーされ、サブフォルダーはコピーされません。ファイル ジオデータセット、ラスター、TIN などの一部のジオデータセットは実際にはフォルダーですが、ジオデータセットでもあるため、コピーされます。フォルダーにレイヤー ファイルが含まれている場合、そのレイヤー ファイルから参照されているすべてのデータも統合され、スクリプト内の arcpy.mp ルーチンから参照データにアクセスできるようになります。

ヒント:

フォルダーの統合では、ツールで使用されることのない大きいサイズのデータセットやファイルによってフォルダーが雑然とするのを避ける必要があります。これは、パッケージ化するデータのサイズを必要以上に増やさないためです。

以下の例は、このフォルダー構造に基づいています。

プロジェクト フォルダーの例
プロジェクト フォルダーの例

相対パスとフォルダー

スクリプトの場所を基準にデータを検出する次の方法は共通パターンです。参照する場合、後に続くスクリプト コードが上記の Scripts フォルダーにあります。ToolData フォルダーに SanFrancisco.gdb が含まれています。SanFrancisco.gdb の中に、Streets という名前のフィーチャクラスがあります。以下のコード サンプルでは、スクリプトの場所 (Scripts フォルダー) からの相対で ToolData フォルダーへのパスが作成されます。

import arcpy
import os
import sys
# Get the pathname to this script, then strip off the
#  script file name to yield the containing folder
#
scriptPath = sys.path[0]
thisFolder = os.path.dirname(scriptPath)
# Construct paths to ../ToolData/SanFrancisco.gdb/Streets and
#                    ../ToolData/Warehouse.lyr
#
toolDataPath = os.path.join(thisFolder, "ToolData")
streetFeatures = os.path.join(toolDataPath, "SanFrancisco.gdb", "Streets")
streetLyr = os.path.join(toolDataPath, "Warehouse.lyr")

上記のコードでは、「ToolData」という文字列 (os.path.join 関数への引数) がテストされ、データが存在するかどうかが確認されます。この場合、スクリプトの場所からの相対位置に ToolData という名前のフォルダーがあります。この ToolData フォルダーが統合されます。フォルダー内のすべてのコンテンツ (上記に従って、サブフォルダーを除く) がパッケージ化されます。

個々のファイルがコピーされるのではなく、フォルダーのコンテンツがコピーされることに注意してください。たとえば、上記のコードで、データセット e:/Warehousing/ToolData/SanFrancisco.gdb/Streets へのパスが作成されるとします。統合処理では、Streets データセットのみを分離してコピーするわけではありません。ToolData フォルダー全体がコピーされます。

ジオデータセットへの絶対パス

絶対パスは、ドライブ文字 (次のサンプル コードでは e:/) から始まるパスです。

streetFeatures = 'e:/Warehousing/ToolData/SanFrancisco.gdb/Streets'

上記のコードでは、Streets データセットとそれが依存する他のすべてのデータ (リレーションシップ クラス、ドメインなど) が統合されます。

ハイブリッドの例

toolDataPath = r'e:\Warehousing\ToolData' warehouseLyr = os.path.join(toolDataPath, "Warehouse.lyrx")

上記のコードでは、ToolData フォルダーのコンテンツ全体が統合されます。フォルダー内のコンテンツ (サブフォルダーを除く) が統合されるため、Warehouse.lyrx は、Warehouse.lyrx から参照されるデータも含めて統合されます。

スラッシュとバックスラッシュ

Windows の表記規則では、パスの区切り文字としてバックスラッシュ (円記号) (\) を使用します。UNIX システムではスラッシュ (/) を使用します。

メモ:

ArcGIS ではどちらを使用してもかまいません。スラッシュであっても、バックスラッシュであっても、該当するオペレーティング システムの表記法に変換されます。

スクリプトでのバックスラッシュ

UNIX 関連のプログラミング言語 (Python や C 言語) では、バックスラッシュ (\) はエスケープ文字と見なされます。たとえば、\t はタブを表します。パスにはバックスラッシュが含まれるので、バックスラッシュがエスケープ文字として使用されないようにする必要があります。最も簡単なのは、次のように r ディレクティブを使用して、パスを Python の未処理文字列に変換する方法です。これは、バックスラッシュを無視するよう Python に指示する方法です。

thePath = r"E:\data\telluride\newdata.gdb\slopes"

他の Python モジュールのインポート

スクリプトが、開発した他のスクリプトをインポートする場合があります。たとえば、次のコードは、myutils という名前の Python モジュールのインポートを示しています。このモジュールは、親スクリプトと同じディレクトリ内にあり、getFIDName という名前のルーチンが含まれています。

import arcpy
import myutils
inFeatures = arcpy.GetParameterAsText(0)
inFID = myutils.getFIDName(inFeatures)

import ステートメントが使用されると必ず、次の順序でスクリプトが特定されます。

  • スクリプトと同じフォルダー。スクリプトがツールボックスに埋め込まれている場合、ツールボックスが格納されているフォルダーが使用されます。
  • システムの PYTHONPATH 変数が参照するフォルダー。
  • システムの PATH 変数が参照するフォルダー。
インポートするスクリプトがこれらのフォルダーのいずれかの中にある場合、スクリプトは統合されます。スキャン処理は再帰的です。上記で説明したすべてのルールを使用して、インポートされたスクリプトもスキャンされてプロジェクト データとインポートがないか確認されます。

インポートするモジュールを参照する別の方法として、sys.path.append メソッドを使用する方法もあります。この方法を使用すると、インポートする必要のあるスクリプトを格納するフォルダーにパスを設定できます。

import arcpy import sys import os
# Append the path to the utility modules to the system path
#  for the duration of this script. #
myPythonModules = r'e:\Warehousing\Scripts' sys.path.append(myPythonModules) import myutils # a Python file within myPythonModules

上記のコードでは、sys.path.append メソッドは引数としてフォルダーを必要とすることに注意してください。'e:\Warehousing\Scripts' はフォルダーであるため、フォルダー全体のコンテンツが統合されます。ここでも、フォルダーのコンテンツをコピーするためのルールが適用されます。ジオデータセットでないサブフォルダーを除く、フォルダー内のすべてがコピーされます。

メモ:

フォルダー内の Python スクリプトをスキャン対象として、プロジェクト データやインポート済みモジュールが検索されることはありません。

ツールの整合チェック コード

スクリプト ツールを作成した経験がある場合は、ユーザー独自のツールの整合チェック ロジックを指定してもかまいません。整合チェック ロジックは、Python を使用して実装されます。整合チェック コードは、他のすべての Python スクリプトと同様に、プロジェクト データとモジュールについてスキャンされます。たとえば、整合チェック ロジックは、投影情報ファイル (*.prj) を含むフォルダー (d:\approved_projections など) を開き、ユーザーがツールの実行時に選択できる空間参照の選択リストを構築します。このフォルダーはツール パラメーターではなく、単にツールの整合チェック スクリプト内で使用されるデータ パスです。Python スクリプトに関する上記のルールと同じルールがここでも適用されます。その結果、d:\approved_projections フォルダーが統合され、パッケージに含められます。

サードパーティ ライブラリ

サードパーティ モジュール (コア Python インストールの一部でないモジュール) は、統合されません。サードパーティ モジュールは、パッケージを解凍したコンピューター上に必ずインストールする必要があります。必要なサードパーティ モジュールを指定するツールとパッケージについてのドキュメントを提供する必要があります。これは、ArcGIS と共にインストールされるサードパーティ モジュール (numpymatplotlibpandas など) には適用されません。