共享 Python 脚本的技术

以下将介绍一些您在与其他用户共享 Python 脚本时可使用的技术。

相对脚本位置查找数据

对于不以参数形式传递的现有数据,您的脚本可能需要使用其路径(程序员称之为硬连接路径)。例如,您可能需要将输出参数的符号系统属性设置为某个现有图层文件,或者需要将数据裁剪为某个已知数据集。

与其他用户共享工具时,您需要确保脚本能够找到其所需数据。为此,建议您使用 ToolShare 文件夹结构。您可以将工程数据和脚本分别放在 ToolDataScripts 文件夹中。如果采用此方式,您始终可以相对于脚本位置找到数据。

当运行脚本时,可按照以下方法查找该脚本的路径:

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 网站 (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 扩展名)以及 sysos 模块。请注意,helloworld 中的 .py 扩展名不是必需的(实际上,是不允许的)。

helloworld.py 脚本实施两个称为 dosomething 的例程(使用 def 语句),dosomething 打印出现较频繁的“Hello world”,而 somethingelse 打印较少出现的“Goodbye world”。当执行 main.py 时,main.py 会调用这两个例程来打印“Hello world”与“Goodbye world”。

以上所示的两个模块缺少许多内容,如导入 arcpy、获取地理处理环境、错误处理等类似内容。在 Python 快速浏览中涵盖了所有这些主题。

Python 查找模块的位置

当执行 main.py 时,import 指令会使 Python 在它的系统目录路径列表中查找名为 helloworld.py 的文件。Python 会首先在当前目录中查找,即包含 import 指令的脚本的目录(在本例中为 main.py)。您可以使用以下代码在交互式 PythonWin 窗口中显示这些路径的列表:

import sys
sys.path

不能在 import 指令中输入路径,如

import E:\SharedScripts\helloworld

而是必须更改 Python 查找模块的目录的列表。此目录列表包含在名为 PYTHONPATH 的 Windows 环境设置中,由 ArcGIS 安装。要更改此设置,请执行以下操作:

  1. 在 Windows“开始”菜单下,单击设置 > 控制面板
  2. 找到“系统”文件并将其打开。
  3. 单击高级选项卡,然后单击环境变量
  4. 系统变量下,滚动至 PYTHONPATH 变量,然后单击将其选中。
    • 如果不存在 PYTHONPATH 变量,则单击新建。在变量名称:文本框中,输入 PYTHONPATH。
    • 变量值:文本框中,输入 <ArcGIS 安装目录>\bin;<ArcGIS 安装目录\arcpy(例如 C:\Program Files\ArcGIS\Desktop10.0\bin;C:\Program Files\ArcGIS\Desktop10.0\arcpy)。
    • 单击确定
  5. 如果存在 PYTHONPATH 变量,则单击编辑

    PYTHONPATH 内容中的第一个条目应该是 <ArcGIS 安装目录>\bin;<ArcGIS 安装目录\arcpy。这是 arcgisscripting 模块所在的位置。您可以追加更多指向包含 Python 模块的目录的路径。这些路径以分号隔开且分号左右不能有任何空格。

您还可以通过以下方式在代码中追加路径

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

共享 Python 模块

如果要将脚本工具提供给其他用户,并且该脚本需要导入其他模块,您可以选择以下两种方法:

  1. 将所有脚本放于同一目录中。
  2. 通知用户在其系统中的某个位置安装其他模块并修改 PYTHONPATH 变量。

不建议使用 sys.path.append(),因为它要求用户更改 Python 代码。

路径和转义字符

基于 UNIX 的编程语言以及 C 编程语言与 Python 类似,都将反斜线 (\) 视为转义字符。例如,\n 用于在写入文本输出时插入一个回车符,而 \t 用于插入制表符。如果脚本中的路径使用反斜线作为分隔符,则 Python 会搜索此分隔符,并在遇到 \n\t 时,分别将其替换为回车符和制表符。(除了 \n\t 外,还有其他的转义字符序列。)

防止此类状况的最简单方法是使用 r 指令将路径转换为 Python 原始字符串,如下所示。这会指示 Python 忽略反斜线。

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

了解有关设置数据路径的详细信息

检查许可

如果您的脚本使用扩展模块,或所需工具在 ArcView 或 ArcEditor 产品级别上不可用,则需要先检查许可和产品级别。

了解有关脚本中的许可检查的详细信息

相关主题


7/10/2012