ArcGIS Python Tool - імпорт спеціального сценарію в клас ToolValidator


9

Минулого тижня я розмістив запитання про налаштування класу ToolValidator і отримав кілька дуже хороших відповідей. Працюючи з запропонованими рішеннями, я створив спеціальний модуль, який виконує запити на db, і буде викликаний класом ToolValidator (для надання значень для випадаючих списків), а також пізніше в сценарії геообробки (щоб отримати інші параметри на основі елементів, вибраних у спадному списку). Однак я не можу насправді викликати спеціальний модуль у класі ToolValidator. Я намагався без успіху приєднатись до шляху. Коли я намагаюся застосувати ці зміни до сценарію, я отримую помилку виконання: [Errno 9] Неправильний дескриптор файлу. Якщо я прокоментую рядок імпорту, помилок не буде.

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

Багато з вас можуть запитати, чому я просто не реалізую спеціальний інструмент з ArcObjects. Причина полягає в тому, що мої кінцеві користувачі не мають привілеїв, необхідних для того, щоб зареєструвати будь-які клітини на своєму комп'ютері.

ОНОВЛЕННЯ: Це сталося зі мною в ArcGIS 10. Цікаво, що я спочатку додавав до шляху всередині функції inicijaliazeParameters класу ToolValidator. Якщо я додаю за межами (тобто поверх) класу 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, і я припускаю, що цей код передається інтерпретатору python у пам'яті, тому __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. Після цього ви можете імпортувати сценарії python у валідатор, використовуючи sys.argv [0]. Це вкаже на папку, в якій знаходився перший скрипт. Після цього ви можете імпортувати необхідний скрипт у клас Validator.

Сценарій 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')

На жаль, не вдається отримати правильне форматування З повагою, Маартен Тромп


3

Нарешті зламали цю жахливу помилку! Наприклад, коли ви намагаєтесь застосувати зміни для імпорту відносного модуля або пакета, ви можете побачити таку помилку:

введіть тут опис зображення

Варіант 1:
Лише для розробника додайте повний шлях до модуля до PYTHONPATH . Вам потрібно буде перезапустити ArcMap / ArcCatalog до того, як він набуде чинності. Використовуйте код нижче, щоб імпортувати модуль з відносного шляху (для розгортання). Не хвилюйтесь, кінцевому користувачеві не потрібно ніяких доповнень до своєї змінної PYTHONPATH, воно буде працювати!

Варіант 2:
Додайте додатковий рядок у код нижче, щоб додати жорстко закодований шлях, наприклад: sys.path.append (r "c: \ temp \ test \ script")
Коли ви готові до розгортання, у вас є сторонній каталог, але це не має значення, все повинно працювати на комп'ютері кінцевого користувача, тому що перший шлях, який ви додали, був відносним каталогом (наша мета полягала в тому, щоб просто пройти діалогове вікно відмови).

Код, загальний для обох варіантів:

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.

У цьому прикладі ім'я каталогу джерела засноване на імені tbx. Цей підхід дозволяє уникнути зіткнень, якщо у вас є два набори інструментів з різними джерелами каталогів. Стандарт, який я використовував для іменування вихідної папки, такий:
TOOLBOXNAME__anything.tbx -> TOOLBOXNAME.src

Чому "все __"? Оскільки бінарні файли не можуть бути об'єднані в нашій DVCS, ми можемо призначати інструменти окремим особам і не турбуватися про втрату змін. Коли інструмент буде доопрацьований, його вирізають і вставляють у майстер.

Також мені знадобилося отримати доступ до файлів у вихідній папці, щоб заповнити спадне меню, скористайтеся цим методом, щоб отримати шлях до панелі інструментів із імпортного модуля:

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

Можливо, код ToolValidator встановлює значення параметра за замовчуванням? Перевірте параметр "Значення за замовчуванням" у властивостях інструмента сценарію.
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, але це не вдалося в операторі імпорту. Чи використовували ви щойно відкритий ArcCatalog перед запуском сценаріїв? Я б міг уявити, що тому ESRI відчуває труднощі з відтворенням помилки ... вона виникає лише в нещодавно відкритому додатку до запуску будь-яких сценаріїв.
MJ

Для мене це працює з нещодавно відкритим ArcCatalog. Цікаво, чи це імпорт класу проти функції, яка є проблемою?
blah238

Дякую, ви можете щось надіслати .... Я смутно пам'ятаю випадок, коли він працював, коли я безпосередньо імпортував функцію, я ще кілька тестую.
MJ

Дуже дивна поведінка ... це діяло б, поки мені не вдалося його зламати. Після її розбиття вона послідовно викинула б помилку. Використання PYTHONPATH на машині розробника або додавання другого жорстко закодованого контуру, як зазначено вище, зробили свою справу.
MJ

0

Мені вдалося перенести свою перевірку у файл py, імпортувавши її та викликавши її в межах існуючої перевірки інструменту TBX. Ключ викликав імпорт всередині конструктора. Якщо я викликав його поза класом 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 (). Там, де це було б легше підтримувати.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.