На прошлой неделе я опубликовал вопрос о настройке класса ToolValidator и получил несколько очень хороших ответов. Работая с предлагаемыми решениями, я создал пользовательский модуль, который выполняет запросы к базе данных, и будет вызываться как классом ToolValidator (для предоставления значений для раскрывающихся списков), так и позже в сценарии геообработки (чтобы получить другие параметры на основе элементов, выбранных в раскрывающихся списках). Однако я не могу вызвать пользовательский модуль в классе ToolValidator. Я пытался присоединиться к пути без удачи. Когда я пытаюсь применить эти изменения к сценарию, я получаю сообщение об ошибке во время выполнения: [Errno 9] Неверный дескриптор файла. Если я закомментирую строку импорта, ошибок нет.
sys.path.append('my_custom_module_directory')
import my_custom_module
Многие из вас могут спросить, почему бы мне не реализовать собственный инструмент с ArcObjects. Причина в том, что мои конечные пользователи не имеют прав, необходимых для регистрации ЛЮБЫХ библиотек на своем компьютере.
ОБНОВЛЕНИЕ: Это происходило со мной в ArcGIS 10. Интересно, что я изначально добавлял путь в функцию initialiazeParameters класса 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: я думаю, что нашел истинную причину своей проблемы. В фрагментах кода в этом посте я добавляю реальные пути (например, C: / Working / SomeFolder) к sys.path. В моем собственном классе 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.
источник
Ответы:
Для этого я после запуска ArcGIS или ArcCatalog сначала запускаю фиктивный инструмент («Выполнить это один раз»), вызывающий скрипт dummy.py. После этого вы можете импортировать скрипты Python в валидатор, используя sys.argv [0]. Это будет указывать на папку, где был расположен первый скрипт. После этого вы можете импортировать необходимый скрипт в класс de Validator.
Сценарий dummy.py, вызываемый инструментом «Запустить один раз»:
Извините, не могу получить правильное форматирование С уважением, Мартен Тромп
источник
Наконец-то взломали эту ужасную ошибку! Например, когда вы пытаетесь применить изменения для импорта относительного модуля или пакета, вы можете увидеть следующую ошибку:
Вариант 1.
Только для разработчика, добавьте полный путь к модулю в PYTHONPATH . Вам нужно будет перезапустить ArcMap / ArcCatalog, прежде чем он вступит в силу. Используйте код ниже, чтобы импортировать модуль из относительного пути (для развертывания). Не волнуйтесь, конечный пользователь не нуждается в каких-либо дополнениях к своей переменной PYTHONPATH, это будет работать!
Вариант 2.
Добавьте дополнительную строку в код ниже, чтобы добавить жестко запрограммированный путь, например: sys.path.append (r "c: \ temp \ test \ scripts").
Когда вы будете готовы к развертыванию, у вас есть посторонний каталог, но это не имеет значения, все должно работать на компьютере конечного пользователя, потому что первый путь, который вы добавили, был относительный каталог (наша цель состояла в том, чтобы просто пройти диалог сбоя).
Код, общий для обоих вариантов:
Обновить
Прощай, злой обрез и оклейка Я обновил пример кода, чтобы класс ToolValidator был импортирован из библиотеки. Я вырезал и вставил только один раз, когда параметры инструмента установлены впервые. Я храню этот фрагмент кода в строке документации импортируемого ToolValidator.
В этом примере имя исходного каталога основано на имени tbx. Этот подход позволяет избежать коллизий, если у вас есть две панели инструментов с разными исходными каталогами. Стандарт, используемый для именования исходных папок, следующий:
TOOLBOXNAME__anything.tbx -> TOOLBOXNAME.src
Почему «все»? Поскольку двоичные файлы не могут быть объединены в нашей DVCS, мы можем назначать инструменты отдельным лицам и не беспокоиться о потере изменений. Когда инструмент завершен, он обрезается и вставляется в мастер.
Мне также нужно было получить доступ к файлам в исходной папке, чтобы заполнить раскрывающийся список, используйте этот метод, чтобы получить путь к панели инструментов из импортированного модуля:
источник
Размещение импорта в верхней части модуля проверки, вне
ToolValidator
класса, кажется, работает нормально для меня - я на 10.0 SP2. Однако я ничего не делаю с импортированным модулем нигде, кроме как вupdateParameters
.источник
Я смог переместить свою проверку в py-файл, импортировав его и вызвав его из существующей проверки инструмента TBX. Ключ вызывал импорт внутри конструктора. Если я вызвал его извне класса ToolValidator, импорт не удался. Вот что у меня было на вкладке проверки TBX.
Моя логика проверки тогда жила в ExportParcelIntersected.ToolValidator (). Где это можно было бы поддерживать проще.
источник