Atualizando módulos importados no ArcGIS Python Toolbox?

15

Ao usar uma caixa de ferramentas python (.pyt) no ArcMap, normalmente seguirei um padrão em que o próprio arquivo .pyt é simplesmente um invólucro para coletar argumentos de entrada e definir as próprias ferramentas. O código de suporte é mantido em módulos testáveis ​​por unidade separados.

Exemplo:

import supporting_module

class MyTool(object):

    ...

    def execute(self, parameters, messages):
        """The source code of the tool."""
        some_input = parameters[0].valueAsText
        some_output = parameters[1].valueAsText

        supporting_module.do_something(some_input, some_output)
        arcpy.SetParameter(2, some_output)

Isso funciona muito bem, mas encontrei um problema frustrante durante o desenvolvimento. Clique com o botão direito do mouse -> Atualizar no .pyt no ArcMap apenas atualiza o código do arquivo .pyt. Ele não atualiza os módulos importados, por isso tenho que fechar e reabrir o ArcMap sempre que alterar alguma coisa lá. Felizmente, como estou testando o código de forma independente, não preciso fazer isso muito, mas ainda é um grande aborrecimento. Existe alguma maneira de contornar isso? Um pouco relacionado - existe alguma maneira de atualizar completamente o console do Python (eu tenho um pacote de sites personalizado que também devo fechar / reabrir o ArcMap para obter alterações também)?

Estou usando o ArcMap 10.2.1.

Josh Werts
fonte

Respostas:

14

Encontrei essa possibilidade, /programming/1517038/python-refresh-reload

A única ressalva é que, se você tiver quaisquer variáveis ​​atribuídas ao módulo, elas precisarão ser atribuídas novamente.

Mas, como você escreveu acima, você pode fazer o seguinte:

import supporting_module
def execute()
  reload(supporting_module)
  ...

Dessa forma, toda vez que você executar a ferramenta, você terá o módulo atualizado. Uma vez concluído o desenvolvimento, isso pode ser retirado.

cndnflyr
fonte
1
Extremamente útil e isso resolve o exemplo simples que eu postei. No entanto, se o support_module também importar outros módulos auxiliares, eles também deverão ser chamados com reload. Acho que é o melhor que conseguiremos, pois faz sentido com a maneira como o Python carrega os módulos - vou marcar o seu como a resposta se algo mais robusto não aparecer no dia seguinte.
Josh Werts 27/03
Muito útil. Descobri que é suficiente ligar reload()imediatamente após a importação do módulo de suporte, na parte superior do arquivo PYT da caixa de ferramentas. Portanto, se a caixa de ferramentas contiver várias ferramentas, não preciso duplicar a recarga na execute()função de cada ferramenta .
Mike Finch
Realmente não entendo como essa resposta resolve o problema. Eu tenho minhas ferramentas armazenadas em arquivos .py e as importo usando from pyfile import Tool, adicionando reload(tool)retornos typeError: reload() argument must be module. Alguma ideia?
Ratnanil 6/02/2018
2
Eu encontrei a solução! importe o arquivo py como um módulo primeiro, recarregue e depois importe a classe dentro do módulo. Veja: stackoverflow.com/a/6946467/4139249
Ratnanil
5

Aqui está uma maneira diferente e mais robusta do que sugeri antes.

Eu não usei esse módulo, mas acho que resolveria o seu problema:

Recarregador de módulo Python

Esta biblioteca implementa um recarregador de módulo baseado em dependência para Python. Diferentemente da função interna reload (), esse recarregador recarregará o módulo solicitado e todos os outros módulos que dependem desse módulo.

Dado o exemplo anterior, isso deve carregar todas as dependências com uma chamada:

import reloader
reloader.enable()

import supporting_module

def execute()
  reloader.reload(supporting_module)
  ...

Esta é a primeira vez que notei este módulo; portanto, se você o implementar em suas ferramentas, comente novamente como ele funciona bem para você.

cndnflyr
fonte
Boa descoberta! Isso funcionou se adicionado exatamente como você mostra. Eu só tenho que clicar com o botão direito do mouse -> atualizar na caixa de ferramentas se o arquivo .pyt for alterado. Os módulos de suporte e seus submódulos estão sendo recarregados com sucesso. Porém, uma ressalva - recebi algumas exceções inexplicáveis ​​de vez em quando e um travamento do ArcMap (embora os travamentos do ArcMap realmente não sejam tão anormais, infelizmente). Nota - Eu só testei isso com o módulo de suporte e um submódulo dependente. Pode relatar a estabilidade no futuro.
Josh Werts 28/03
1
Super, obrigado por relatar. Sim, ao dirigir o ArcMap, às vezes me sinto um boneco de teste de colisão.
cndnflyr
Infelizmente, eu já deparei com muitos problemas de estabilidade com este recarregador, então alterei a resposta selecionada para a função interna recarregar () original. Às vezes, mais simples é melhor!
Josh Werts 31/03