ArcGIS Python Tool-ToolValidator 클래스로 사용자 정의 스크립트 가져 오기


9

지난주 ToolValidator 클래스 사용자 정의에 대한 질문 을 게시했으며 매우 좋은 답변을 얻었습니다. 제안 된 솔루션을 사용하여 db에서 쿼리를 수행하는 사용자 정의 모듈을 만들었으며 ToolValidator 클래스 (드롭 다운 목록의 값을 제공하기 위해)와 나중에 지오 프로세싱 스크립트에서 호출됩니다 (기타 드롭 다운 목록에서 선택한 항목을 기반으로하는 매개 변수). 그러나 실제로 ToolValidator 클래스에서 사용자 지정 모듈을 호출 할 수 없습니다. 나는 운없이 길을 추가하려고 노력했다. 이러한 변경 사항을 스크립트에 적용하려고하면 런타임 오류가 발생합니다. [Errno 9] 잘못된 파일 설명자입니다. 가져 오기 줄을 주석 처리하면 오류가 없습니다.

sys.path.append('my_custom_module_directory')
import my_custom_module

많은 사람들이 왜 ArcObjects로 커스텀 툴을 구현하지 않는지 묻습니다. 그 이유는 최종 사용자가 자신의 컴퓨터에 dll을 등록하는 데 필요한 권한이 없기 때문입니다.

업데이트 : 이것은 ArcGIS 10에서 나에게 발생했습니다. 흥미롭게도, 처음에는 ToolValidator 클래스의 initialiazeParameters 함수 내부의 경로에 추가하고있었습니다. ToolValidator 클래스의 외부 (즉, 위에)를 추가하면 모든 것이 예상대로 작동합니다.

sys.path.append('C:/Working/SomeFolder')
import somescript -------->THIS WORKS

class ToolValidator:
  """Class for validating a tool's parameter values and controlling
  the behavior of the tool's dialog."""

  def __init__(self):
    """Setup arcpy and the list of tool parameters."""
    import arcpy
    sys.path.append('C:/Working/SomeFolder')
    import somescript -------> THIS DOESNT WORK
    self.params = arcpy.GetParameterInfo()

업데이트 2 : 내 문제의 진정한 원인을 찾았습니다. 이 게시물의 코드 스 니펫에서 sys.path에 실제 경로 (예 : C : / Working / SomeFolder)로 보이는 것을 추가했습니다. 실제 ToolValidator 클래스에서 os.path.dirname(__file__)+ "\ my_special_folder ..."를 사용하여 상대 경로를 구성하고 있었습니다. os.path.dirname(__file__)ToolValidator 클래스가 포함되어 있기 때문에 도구 상자의 경로를 반환 할 것으로 예상했습니다 . 나는 이것이 사실이 아니라는 것을 알게되었습니다. 내가 알 수있는 한 ToolValidator 클래스는 실제로 .py 파일에 작성되지 않으며이 코드가 메모리의 파이썬 인터프리터에 전달되므로 __file__쓸모가 없거나 임시 스크립트가 지속되고 execfile ( path_to_script)가 호출되어 다시 렌더링됩니다.__file__쓸모없는. 내가 놓친 다른 이유가 있다고 확신합니다.

간단히 말해, 하드 코딩 된 경로를 사용하면 sys.append는 어디에서나 작동하며 상대 경로는 ToolValidator 클래스에서 제대로 작동하지 않습니다.


9.3 또는 10입니까?
Jason Scheirer

Esri에서이를 재현하는 데 문제가 있습니다. 원인을 분리하면 10.0 SP3의 수정 사항을 백 포트 할 수 있습니다. 그 동안, 나는 당신이 후자의 사용 패턴이 아니라 전자에 집착했다고 가정합니다.
Jason Scheirer

답변:


3

내가하는 방법은 ArcGIS 또는 ArcCatalog를 시작한 후 먼저 dummy.py 스크립트를 호출하는 더미 도구 ( "한 번만 실행")를 실행하는 것입니다. 그런 다음 sys.argv [0]을 사용하여 유효성 검사기에서 Python 스크립트를 가져올 수 있습니다. 첫 번째 스크립트가있는 폴더를 가리 킵니다. 그런 다음 유효성 검사기 클래스에서 필요한 스크립트를 가져올 수 있습니다.

"한번만 실행"도구에서 호출 한 dummy.py 스크립트 :

import arcgisscripting, sys, os
gp = arcgisscripting.create(9.3)

# set up paths to Toolshare, scripts en Tooldata
scriptPath = sys.path[0]  
toolSharePath = os.path.dirname(scriptPath)
toolDataPath = toolSharePath + os.sep + "ToolData"
gp.addmessage("scriptPath: " + scriptPath)
gp.addmessage("toolSharePath: " + toolSharePath)
gp.addmessage("toolDataPath: " + toolDataPath)

# Use this to read properties, VERY handy!!
import ConfigParser
config = ConfigParser.SafeConfigParser()
config.readfp(open(scriptPath + os.sep + 'properties.ini'))
activeOTAP = config.get('DEFAULT', 'activeOTAP')
activeprojectspace = config.get('DEFAULT', 'activeprojectspace')
activeproject = config.get('DEFAULT', 'activeproject')
activesdeconnection = config.get('DEFAULT', 'activesdeconnection')

죄송합니다. 형식을 올바르게 지정할 수 없습니다. 감사합니다. Maarten Tromp


3

마침내이 끔찍한 벌레를 깨뜨 렸습니다! 예를 들어 상대 모듈 또는 패키지를 가져 오기 위해 변경 사항을 적용하려고하면 다음 오류가 표시 될 수 있습니다.

여기에 이미지 설명을 입력하십시오

옵션 1 :
개발자의 경우, 모듈의 전체 경로를 PYTHONPATH에 추가하십시오 . 적용하기 전에 ArcMap / ArcCatalog를 다시 시작해야합니다. 아래 코드를 사용하여 상대 경로 (배포 용)에서 모듈을 가져옵니다. 걱정하지 마십시오. 최종 사용자는 PYTHONPATH 변수를 추가 할 필요가 없습니다.

옵션 2 :
아래 코드에 추가 코드를 추가하여 하드 코드 된 경로를 추가하십시오 (예 : sys.path.append (r "c : \ temp \ test \ scripts"))
배포 할 준비가되면 추가 한 첫 번째 경로는 상대 디렉터리이기 때문에 최종 사용자의 컴퓨터에서 모두 작동해야합니다 (우리의 목표는 실패 대화 상자를 통과하는 것입니다).

두 옵션에 공통 인 코드 :

import os
import sys

tbxPath = __file__.split("#")[0]
srcDirName = os.path.basename(tbxPath).rstrip(".tbx").split("__")[0] + ".src" 
tbxParentDirPath =  os.path.dirname(tbxPath)
srcDirPath = os.path.join(tbxParentDirPath, srcDirName)

sys.path.append(srcDirPath)
# sys.path.append(r"c:\temp\test\scripts")  #option2

from esdlepy.metrics.validation.LandCoverProportions import ToolValidator

최신 정보

작별 인사 잘라 내기 및 붙여 넣기! ToolValidator 클래스를 라이브러리에서 가져 오도록 코드 샘플을 업데이트했습니다. 공구 매개 변수를 처음 설정할 때 한 번만 잘라 붙여 넣기합니다. 이 코드 스 니핏을 가져 오는 ToolValidator의 docstring에 저장합니다.

이 예에서 소스 디렉토리 이름은 tbx 이름을 기반으로합니다. 이 방법은 소스 디렉토리가 다른 두 개의 도구 상자가있는 경우 충돌을 피합니다. 소스 폴더 이름 지정에 사용한 표준은 다음과 같습니다.
TOOLBOXNAME__anything.tbx-> TOOLBOXNAME.src

왜 "__anything"입니까? 이진 파일은 DVCS에 병합 할 수 없기 때문에 개인에게 도구를 할당 할 수 있으며 변경 내용을 잃을 염려가 없습니다. 공구가 완성되면 공구를 잘라 마스터에 붙여 넣습니다.

또한 소스 폴더의 파일에 액세스하여 드롭 다운을 채우고이 방법 을 사용 하여 가져온 모듈 내에서 도구 상자의 경로를 가져와야했습니다.

import __main__
tbxPath = __main__.__file__.split("#")[0]

ToolValidator 코드가 매개 변수의 기본값을 설정하고있을 수 있습니까? 스크립트 도구 속성에서 매개 변수의 'Default Value'설정을 확인하십시오.
blah238

제안 해 주셔서 감사합니다. 확인했는데 도구 상자에 기본값이 설정되어 있지 않습니다 ... 그러나 도구 상자를 복사하고 모든 이름을 변경했지만 값이 여전히 두 사본 모두에서 유지되었습니다. 따라서 캐시 아이디어를 버리고 실제로 .tbx 파일에 저장 될 수 있다고 제안합니다. 이는 여전히 이상한 동작입니다.
MJ

2

ToolValidator클래스 외부에서 유효성 검사 모듈 상단에 가져 오기를 넣으면 나에게 잘 작동하는 것 같습니다 .10.0 SP2에 있습니다. 그러나 가져온 모듈로 어디에서나 아무것도하지 않고 updateParameters있습니다.

import os
import sys
scriptDir = os.path.join(os.path.dirname(__file__.split("#")[0]), "Scripts") 
sys.path.append(scriptDir)
from someModuleInScriptDir import someFunction

class ToolValidator:
    ...

ToolValidator 클래스 외부에서 가져 오기를 시도했지만 import 문에서 실패합니다. 스크립트를 실행하기 전에 새로 열린 ArcCatalog를 사용하고 있었습니까? ESRI가 오류를 재현하는 데 어려움을 겪고있는 이유라고 생각합니다. 스크립트를 실행하기 전에 새로 열린 응용 프로그램에서만 발생합니다.
MJ

새로 열린 ArcCatalog와 함께 작동합니다. 클래스 대 문제를 가져 오는 함수인지 궁금합니다.
blah238

고마워, 당신은 뭔가에있을 수도 있습니다 .... 나는 함수를 직접 가져올 때 그것이 효과가 있었던 경우를 모호하게 기억합니다. 나는 더 많은 테스트를 할 것입니다.
MJ

매우 이상한 행동입니다. 그것을 깨고 나면 지속적으로 오류가 발생합니다. 위에서 설명한 것처럼 개발자 컴퓨터에서 PYTHONPATH를 사용하거나 두 번째 하드 코딩 된 경로를 추가하면 트릭을 수행 할 수 있습니다.
MJ

0

가져 오기 및 기존 TBX의 도구 유효성 검사 내에서 호출하여 유효성 검사를 py 파일로 옮길 수있었습니다. 키는 생성자 내에서 가져 오기를 호출했습니다. ToolValidator 클래스 외부에서 호출하면 가져 오기에 실패했습니다. TBX의 유효성 검사 탭에 내가 가지고있는 것이 있습니다.

import arcpy
import os
import sys

class ToolValidator(object):
   """Class for validating a tool's parameter values and controlling
   the behavior of the tool's dialog."""

def __init__(self):
   """Setup arcpy and the list of tool parameters."""
   self.scriptDir = os.path.dirname(__file__.split("#")[0])
   sys.path.append(self.scriptDir)
   import ExportParcelIntersected
   self.validator = ExportParcelIntersected.ToolValidator()
   self.params = self.validator.params

 def initializeParameters(self):
   """Refine the properties of a tool's parameters.  This method is
   called when the tool is opened."""
   self.validator.initializeParameters()
   return

 def updateParameters(self):
   """Modify the values and properties of parameters before internal
   validation is performed.  This method is called whenever a parameter
   has been changed."""
   self.validator.updateParameters()
   return

 def updateMessages(self):
   """Modify the messages created by internal validation for each tool
   parameter.  This method is called after internal validation."""
   self.validator.updateMessages()
   return

내 유효성 검사 논리는 ExportParcelIntersected.ToolValidator ()에있었습니다. 더 쉽게 유지 될 수있는 곳.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.