Eu havia postado uma pergunta na semana passada sobre como personalizar uma classe ToolValidator e obtive algumas respostas muito boas. Ao trabalhar com as soluções propostas, criei um módulo personalizado que executa consultas em um banco de dados e será chamado pela classe ToolValidator (para fornecer valores para as listas suspensas) e posteriormente no script de geoprocessamento (para obter outras informações). parâmetros com base nos itens selecionados nas listas suspensas). No entanto, não consigo chamar o módulo personalizado na classe ToolValidator. Eu tenho tentado acrescentar ao caminho sem sorte. Quando tento aplicar essas alterações ao script, recebo um erro de tempo de execução: [Erro 9] Descritor de arquivo incorreto. Se eu comentar a linha de importação, não haverá erros.
sys.path.append('my_custom_module_directory')
import my_custom_module
Muitos de vocês podem estar se perguntando por que não apenas implemento uma ferramenta personalizada com o ArcObjects. O motivo é que meus usuários finais não têm os privilégios necessários para registrar QUALQUER dll no computador.
UPDATE: Isso estava acontecendo comigo no ArcGIS 10. Curiosamente, eu estava inicialmente acrescentando o caminho dentro da função initialiazeParameters da classe ToolValidator. Se eu fizer o acréscimo fora (ou seja, em cima) da classe ToolValidator, tudo funcionará conforme o esperado.
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()
ATUALIZAÇÃO 2: Acho que encontrei a verdadeira causa do meu problema. Nos trechos de código desta postagem, anexei o que parecem ser caminhos reais (ex: C: / Working / SomeFolder) ao sys.path. Na minha classe ToolValidator real, eu estava construindo um caminho relativo usando os.path.dirname(__file__)
+ "\ my_special_folder ...". Eu estava prevendo que os.path.dirname(__file__)
retornaria o caminho da caixa de ferramentas, uma vez que contém a classe ToolValidator. Eu vim para descobrir que este não é o caso. Pelo que sei, a classe ToolValidator nunca é realmente gravada em um arquivo .py, e especulo que esse código seja passado para o interpretador python na memória, por isso __file__
é inútil, ou algum script temporário é mantido e, em seguida, é executado o executável ( path_to_script) é chamado, renderizando novamente__file__
sem utilidade. Tenho certeza de que há outras razões pelas quais também estou ausente.
Para encurtar a história, se eu usar um caminho codificado, o sys.append funcionará em qualquer lugar, os caminhos relativos não funcionarão tão bem na classe ToolValidator.
fonte
Respostas:
A maneira como faço isso é, depois de iniciar o ArcGIS ou ArcCatalog, primeiro execute uma ferramenta fictícia ("Execute isso uma vez") chamando um script dummy.py. Depois disso, você pode importar scripts python no validador usando sys.argv [0]. Isso apontará para a pasta onde o primeiro script foi localizado. Depois disso, você pode importar o script necessário na classe Validator.
O script dummy.py chamado pela ferramenta "Executar isso uma vez":
Desculpe, não é possível obter a formatação correta Atenciosamente, Maarten Tromp
fonte
Finalmente quebrou esse bug horrível! Por exemplo, ao tentar aplicar alterações na importação de um módulo ou pacote relativo, você poderá ver o seguinte erro:
Opção 1:
Apenas para o desenvolvedor, adicione o caminho completo ao módulo no PYTHONPATH . Você precisará reiniciar o ArcMap / ArcCatalog antes que ele entre em vigor. Use o código abaixo para importar o módulo de um caminho relativo (para implantação). Não se preocupe, o usuário final não precisa de acréscimos à sua variável PYTHONPATH, ele funcionará!
Opção 2:
adicione uma linha adicional ao código abaixo para anexar o caminho codificado, por exemplo: sys.path.append (r "c: \ temp \ test \ scripts")
Quando estiver pronto para implantar, você terá um diretório externo, mas isso não importa, todos devem funcionar no computador do usuário final, porque o primeiro caminho que você adicionou foi o diretório relativo (nosso objetivo era apenas ultrapassar o diálogo de falha).
Código comum a ambas as opções:
Atualizar
Adeus corte e colagem do mal! Atualizei o exemplo de código para que a classe ToolValidator seja importada da biblioteca. Eu recordo e colo apenas uma vez quando os parâmetros da ferramenta são definidos pela primeira vez. Eu armazeno esse snippit de código na documentação do ToolValidator sendo importado.
Neste exemplo, o nome do diretório de origem é baseado no nome do tbx. Essa abordagem evita colisões se você tiver duas caixas de ferramentas com diretórios de origem diferentes. O padrão que usei para nomear pastas de origem é o seguinte:
TOOLBOXNAME__anything.tbx -> TOOLBOXNAME.src
Por que o "__qualquer coisa"? Como os arquivos binários não podem ser mesclados em nosso DVCS, podemos atribuir ferramentas a indivíduos e não nos preocupar em perder alterações. Quando a ferramenta é finalizada, ela é recortada e colada no mestre.
Eu também precisava acessar arquivos na pasta de origem para preencher uma lista suspensa, use este método para obter o caminho para a caixa de ferramentas de dentro do seu módulo importado:
fonte
Colocando as importações na parte superior do módulo de validação, fora da
ToolValidator
classe parece funcionar bem para mim - estou no 10.0 SP2. No entanto, não estou fazendo nada com o módulo importado em nenhum outro lugar, exceto noupdateParameters
.fonte
Consegui mover minha validação para um arquivo py importando-o e chamando-o a partir da validação da ferramenta do TBX existente. A chave estava chamando a importação dentro do construtor. Se eu chamei de fora da classe ToolValidator, a importação falhou. Aqui está o que eu tinha na guia de validação do TBX.
Minha lógica de validação residia em ExportParcelIntersected.ToolValidator (). Onde poderia ser mantido mais fácil.
fonte