Python スクリプトの共有方法

以下に、Python スクリプトを共有するときに使用できるいくつかの方法について説明します。

スクリプトの場所に基づいたデータ検索

スクリプトによっては、プログラマがハードワイヤード パスと呼ぶ、引数として渡されるものではない既存のデータへのパスが必要です。たとえば、出力パラメータのシンボル プロパティを既存のレイヤ ファイルに設定しなければならない場合や、データを既知のデータセットにクリップしなければならない場合があるかもしれません。

他者とツールを共有する場合は、スクリプトが必要なデータを見つけることができる状態を確保する必要があります。この方法として適切なものに、[ToolShare] フォルダ構造を使って、[ToolData] フォルダにプロジェクト データを配置し、スクリプトを [Scripts] フォルダに配置するというアプローチがあります。この方法を用いれば、確実にスクリプトの場所に基づいてデータを特定できます。

スクリプトを実行したときにスクリプトへのパスを特定する場合は、次の手順に従います。

scriptPath = sys.path[0]

この場所がわかれば、この場所に基づいてプロジェクト データを特定できます。これは、次のコード スニペットに示されています。

import arcpy
import os
import sys

# Get the pathname to this script
#
scriptPath = sys.path[0]
arcpy.AddMessage("Script folder: " + scriptPath)

# Get the pathname to the ToolShare folder
#
toolSharePath = os.path.dirname(scriptPath)
arcpy.AddMessage("ToolShare folder: " + toolSharePath)

# Now construct pathname to the ToolData folder
#
toolDataPath = os.path.join(toolSharePath, "ToolData")
arcpy.AddMessage("ToolData folder: " + toolDataPath)

# Create the pathname to the parks feature class found in the ToolData folder
#
parkPath = os.path.join(toolDataPath, "Project.gdb/Parks")
arcpy.AddMessage("Parks feature class: " + parkPath)
注意注意:

スクリプト コードを埋め込むと、sys.path[0] によってツールボックスの場所(コードの場所)が返されます。

テンポラリ ワークスペースの特定

スクリプト内にテンポラリ データを作成する場合は、テンポラリ データの作成とその後の削除のためのテンポラリ ワークスペースが必要です。

テンポラリ ワークスペースを選択するうえで注意すべきことをいくつか紹介します。

次のコードの例には、非常に確実なテンポラリ ワークスペースの選択が示されています。このコードは、

import arcpy
from arcpy import env
import sys
import os

def getScratchWorkspace(outDataset):
  # outDataSet is assumed to be the full pathname to a dataset. Typically,
  #  this would be a tool's output parameter value.
  #
  # Get the scratch workspace environment. If it's set, just return it.
  #
  scratchWS = env.scratchWorkspace
  if scratchWS:
    return scratchWS
 
  # Let's go fishing...
  #
  # If you're using the ToolShare folder structure, look for scratch.gdb in
  #  the Scratch folder.
  #
  scriptPath      = sys.path[0]
  toolSharePath   = os.path.dirname(scriptPath)
  scratchWS       = os.path.join(toolSharePath, "Scratch/scratch.gdb")
  if not arcpy.Exists(scratchWS):
    scratchWS = ""

  # No scratch workspace environment and no scratch.gdb in the ToolShare folder
  #
  if not scratchWS:
    # Get the workspace of the output dataset (if any passed in)
    #  by going up one level
    #
    if outDataset:
      scratchWS = os.path.dirname(str(outDataset))

      # If this isn't a workspace, go up another level and
      #  test again. 
      #
      desc = arcpy.Describe(scratchWS)
      if desc.dataType.upper() <> "WORKSPACE":
        scratchWS = os.path.dirname(scratchWS)
        desc = arcpy.Describe(scratchWS)
        if desc.dataType.upper() <> "WORKSPACE":
          scratchWS = ""

  # If we have a workspace, make sure it's not a remote (SDE) database.
  #  If it is remote, set workspace to the system temp directory.
  #
  # If we don't have a workspace, just set it to the system temp directory.
  #
  usingTemp = False
  if scratchWS:
      desc = arcpy.Describe(scratchWS)
      if desc.workspaceType.upper() == "REMOTEDATABASE":
          scratchWS = arcpy.GetSystemEnvironment("TEMP")
          usingTemp = True
  else:
      scratchWS = arcpy.GetSystemEnvironment("TEMP")
      usingTemp = True

  # If we're using the system temp directory (a shapefile workspace), look 
  #  for a scratch file geodatabase.  If it exists, use it.  If it doesn't, 
  #  create it.
  #
  if usingTemp:
    scratchWS = os.path.join(scratchWS, "scratch.gdb")
    if arcpy.Exists(scratchWS):
      return scratchWS
    else:
      arcpy.CreateFileGDB_management(arcpy.GetSystemEnvironment("TEMP"),
                                     "scratch.gdb") 

  return scratchWS

# Main demonstration routine
#  One optional input parameter, a feature class. 
#
aDatasetpath = arcpy.GetParameterAsText(0)
scratch = getScratchWorkspace(aDatasetpath)
arcpy.AddMessage("Scratch workspace: " + scratch)

# Create a scratch feature class in the scratch workspace
#
scrname = arcpy.CreateScratchName("temp", "","featureclass", scratch)

arcpy.AddMessage("Scratch feature class is: " + scrname)
arcpy.CreateFeatureclass_management(scratch, os.path.basename(scrname), "point")
arcpy.AddMessage(arcpy.GetMessages())

Python モジュールの共有

他の最近のプログラミング言語と同様に、Python でも、他の Python スクリプトにあるルーチンを呼び出すことができます。Python コードを開発すればするほど、スクリプト間での共有のための Python ルーチンの開発が望まれるでしょう。このセクションでは、ルーチンの共有方法を簡単に説明し、公式の Python Web サイト(http://www.python.org)をはじめとした、ルーチンの共有を効果的に調査および実装できるようにする十分な情報をご紹介します。

スクリプト helloworld.py の内容は次のようになっています。

def dosomething():
    print "Hello world"
def somethingelse():
    print "Goodbye world"

スクリプト main.py の内容は次のようになっています。

import sys, os, helloworld
helloworld.dosomething()
helloworld.somethingelse()

スクリプト main.py は、helloworld モジュール(モジュール名はスクリプト名から「.py」拡張子を除外したものです)を、sys および os モジュールとともにインポートします。helloworld の拡張子「.py」は必要ありません(実際、この使用は認められません)。

スクリプト helloworld.py は、あちこちで目にする「Hello world」を印刷する dosomething と、これよりも目にする頻度の低い「Goodbye world」を印刷する somethingelse と呼ばれる 2 つのルーチンを(def ステートメントで)実装します。main.py が実行されると、「Hello world」と「Goodbye world」を印刷するこれらの 2 つのルーチンが呼び出されます。

上記のこれら 2 つのモジュールには、arcpy のインポート、ジオプロセシング環境の取得、エラー対応など、多数の項目が入っていません。これらのトピックについては、「Python の概要」をご参照ください。

Python によるモジュールの検索先

main.py が実行されると、インポート ディレクティブは、システム ディレクトリ パスのリストにある helloworld.py という名前のファイルを Python に検索させます。Python が最初に検索する場所は、インポートディレクティブを格納したスクリプトと同じディレクトリである現在のディレクトリ(この場合はmain.py)です。これらのパスは PythonWin の対話形式のウィンドウに一覧表示できます。

import sys
sys.path

次のように、インポート ディレクティブにパスを入力することはできません

import E:\SharedScripts\helloworld

そうではなく、Python によるモジュールの検索先となるディレクトリのリストを変更する必要があります。このディレクトリのリストには、ArcGIS によってインストールされる PYTHONPATH と呼ばれる Windows の環境設定が格納されています。この設定を変更するには、次の手順を実行します。

  1. Windows の[スタート] メニューで、[設定] [コントロール パネル] の順にクリックします。
  2. [System] ファイルを見つけて、開きます。
  3. [詳細設定] タブをクリックし、[環境変数] をクリックします。
  4. [システム環境変数] の下で PYTHONPATH 変数にスクロールし、これをクリックして選択します。
    • PYTHONPATH 変数がない場合は、[新規作成] をクリックします。[変数名] テキスト ボックスに「PYTHONPATH」と入力します。
    • [変数値] テキスト ボックスに、「<ArcGIS install directory>\bin;<ArcGIS install directory\arcpy(例として、C:\Program Files\ArcGIS\Desktop10.0\bin;C:\Program Files\ArcGIS\Desktop10.0\arcpy)」と入力します。
    • [OK] をクリックします。
  5. PYTHONPATH 変数が存在する場合は、[編集] をクリックします。

    PYTHONPATH の内容に、最初のエントリとして <ArcGIS install directory>\bin;<ArcGIS install directory\arcpy が含まれているはずです。arcgisscripting モジュールはここにあります。これ以外にも Python モジュールを格納したディレクトリへのパスを追加することができます。パスはセミコロンで区切り、セミコロンの前後にはスペースを入れないでください。

パスはコード内に追加することもできます。

sys.path.append("e:\sharedmodules")

Python モジュールの共有

他のユーザにスクリプト ツールを配布する場合で、そのスクリプトが他のモジュールをインポートする場合には、2 つのオプションがあります。

  1. すべてのスクリプトを同一ディレクトリに格納します。
  2. ユーザには、追加的なモジュールをユーザのシステムの任意の場所にインストールして、PYTHONPATH 変数を変更するよう指示します。

ユーザによる Python コードの変更が必要となるため、sys.path.append() の使用はお勧めしません。

パスとエスケープ文字

Python のように、UNIX と C プログラミング言語に根ざしたプログラミング言語では、円記号(バックスラッシュ)[\]がエスケープ文字として扱われます。たとえば \n は、テキスト出力を書き出す時にキャリッジ リターンを挿入する場合に使用され、\t はタブ記号を挿入する場合に使用されます。スクリプトのパスで円記号が区切り記号として使用されている場合、Python はこれをスキャンして、\n があればこれをキャリッジ リターンに、\t があればこれをタブに置き換えます(エスケープ文字の組み合わせは \n\t だけではありません)。

この問題を避ける最も簡単な方法は、以下に示す r ディレクティブを使用してパスを未加工の Python 文字列に変換することです。これにより、Python に円記号を無視するよう指示することができます。

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

データへのパスの設定の詳細

ライセンスの確認

エクステンションを使用しているか、ArcView や ArcEditor 製品レベルでは利用できないツールに依拠しているスクリプトの場合は、まずライセンスと製品レベルを確認する必要があります。

スクリプトにおけるライセンス確認の詳細

関連項目


7/10/2012