Escolar Documentos
Profissional Documentos
Cultura Documentos
OBJETIVOS DA DISCIPLINA:
A disciplina visa abordar os conceitos básicos da linguagem de programação Python e
utilizá-la de forma integrada em ambiente de geoprocessamento como o ArcGIS.
JUSTIFICATIVA:
Os profissionais que trabalham na área de meio ambiente geralmente possuem
conhecimento e já estão familiarizados com os conceitos de SIG e geoprocessamento sem
que, contudo, trabalhem com uma linguagem de programação. Muitas vezes os usuários
apenas fazem uso de interfaces gráficas (GUI) por meio das ferramentas já disponíveis nos
softwares SIG, mas em algum momento se faz necessário estender os recursos, automatizar
processos, ou apenas trabalhar de forma mais eficiente para completar os objetivos
primários para responder a perguntas baseadas no espaço geográfico. Desta maneira, a
disciplina busca ensinar os alunos a desenvolver scripts para que este possa incorporá-los
ao fluxo de seu trabalho.
CONTEÚDO:
Introdução ao Python e ArcPy. Uso ferramentas de geoprocessamento de forma
automatizada. Trabalho com feições e geometrias em formato vetorial. Trabalho com
arquivos rasters. Criação de Python toolboxes e add-ins.
BIBLIOGRAFIA:
Bielenki, C. Jr; Barbassa, A. P. Geoprocessamento e Recursos Hídricos: Aplicações
Práticas. EDUFSCar, São Carlos, 2012.
Paul A. Zandbergen, Python Scripting for ArcGIS, ESRI Press, Califórnia, 2013.
Docentes responsáveis:
Agosto, 2019
Este material está dividido em 4 etapas:
5
Etapa 2: Fundamentos de Programação com Python
Na etapa 2 trabalhamos com conceitos fundamentais de programação e técnicas de
solução de problemas que são comuns à maioria das linguagens de programação. O objetivo
desta etapa é prepará-lo para aprender qualquer linguagem de programação que possa ser
exigida em seu trabalho. A lição também mostra como sintetizar esses fundamentos para
abordar problemas de programação. Você é orientado sobre onde procurar ajuda para se
tornar um programador autossuficiente.
Esboço da etapa 2:
• Mais fundamentos do Python
o Listas
o Loopings
o Estruturas de decisão
o Manipulação de strings
o Colocando tudo junto
• Solução de problemas e obtenção de ajuda
o Problemas potenciais e diagnóstico rápido
o Usando o depurador do PythonWin
o Imprimindo mensagens do geoprocessador
o Outras fontes de ajuda
• Projeto 2: Reprojeção em lote de conjuntos de dados vetoriais
6
Etapa 4: Python Prático para o Analista de SIG
Nesta etapa abordam-se conceitos relativamente avançados que ajudarão você a se
tornar um programador SIG especialmente útil. Isso inclui a criação de código reutilizável por
meio de funções e módulos, análise de texto e gravação de feições geométricas em
conjuntos de dados vetoriais no ArcGIS. Na lição discute-se como usar arquivos em lote e
os utilitários de agendamento do sistema operacional para automatizar a execução de
scripts. Também se explica como automatizar algumas funções para layouts de mapas no
ArcMap usando Python.
As seções desta lição são mais longas e contêm exemplos de código mais complexos
do que as lições anteriores. Nesse ponto do curso, você deve ter conhecimento para
entender esses exemplos. O objetivo é que você se sinta confiante o suficiente para ler
qualquer script não familiar depois de concluir esta lição. Você também deve sentir que tem
conhecimento adquirido suficiente para abordar a maioria dos desafios de automação por
meio de scripts.
Esboço da etapa 4:
• Funções e módulos
• Leitura e análise de texto
• Geometrias de feições
• Automação com arquivos em lote e tarefas de agendamento
• Executando qualquer ferramenta da caixa de ferramentas
• Trabalhando com documentos de mapas
• Limitações do script Python no ArcGIS
• Projeto 4
Projeto Final
No final do curso, você é obrigado a concluir um projeto de script individual que aplica
o conhecimento que você adquiriu ao longo do curso. Você é encorajado a escolher um
projeto que seja útil para a sua pesquisa atual, se possível.
7
Etapa 1: Introdução à modelagem SIG e Python
Objetivos da etapa 1
8
• Automação torna o trabalho mais fácil. Depois de automatizar um processo,
você não precisa se esforçar tanto para lembrar quais ferramentas usar ou a sequência
correta em que elas devem ser executadas.
• Automação torna o trabalho mais rápido. Um computador pode abrir e
executar ferramentas em sequência muito mais rápido do que você pode realizar a
mesma tarefa apontando e clicando.
• A automação torna o trabalho mais preciso. Toda vez que você executa uma
tarefa manual em um computador, há uma chance de erro. A chance se multiplica com
o número e a complexidade das etapas em sua análise, bem como o cansaço incorrido
pela repetição da tarefa várias vezes. Em contraste, uma vez que uma tarefa
automatizada é configurada, um computador é confiável para executar a mesma
sequência de etapas a cada vez, para um número potencialmente infinito de ciclos.
O ArcGIS oferece três maneiras para os usuários automatizarem suas tarefas de
geoprocessamento. Essas três opções diferem na quantidade de habilidade necessária para
produzir a solução automatizada e na variedade de cenários que cada uma pode endereçar.
A primeira opção é construir um modelo usando o Model Builder. O Model Builder é um
programa interativo que permite ao usuário “encadear” ferramentas, usando a saída de uma
ferramenta como entrada em outra. Talvez o recurso mais atrativo do Model Builder seja que
os usuários podem automatizar fluxos de trabalho SIG bastante complexos sem a
necessidade de programação. Você aprenderá a usar o Model Builder no início deste curso.
Algumas tarefas de automação exigem maior flexibilidade do que a oferecida pelo
Model Builder e, para esses cenários, é recomendável que você escreva programas de
computador ou scripts curtos. A maior parte deste curso está relacionada com a escrita de
scripts.
Um script geralmente executa alguns procedimentos sequenciais de etapas. Dentro de
um script, você pode executar ferramentas SIG individualmente ou encadeá-las. Você pode
inserir lógica condicional em seu script para lidar com casos em que diferentes ferramentas
devem ser executadas, dependendo da saída da operação anterior. Você também pode
incluir iterações ou loops em um script para repetir uma única ação quantas vezes forem
necessárias para realizar uma tarefa.
Existem linguagens de script especiais para escrever scripts, incluindo Python, JScript
e Perl. Geralmente, essas linguagens têm uma sintaxe mais básica e são mais fáceis de
aprender do que outras linguagens, como C, Java ou Visual Basic.
Embora o ArcGIS suporte várias linguagens de script para trabalhar com suas
ferramentas, a ESRI enfatiza o Python em sua documentação e inclui o Python com a
instalação do ArcGIS. Neste curso, trabalharemos estritamente com o Python por esse
motivo, bem como o fato de que o Python pode ser usado para muitas outras tarefas de
manipulação de arquivos e dados fora do ArcGIS. Você aprenderá o básico sobre a
linguagem Python, como escrever um script e como manipular e analisar dados SIG usando
scripts. Por fim, você aplicará seu novo conhecimento em Python a um projeto final, no qual
escreverá um script de sua escolha que poderá aplicar diretamente ao seu trabalho.
Uma terceira opção disponível para os usuários do ArcGIS que procuram automatizar
o geoprocessamento é construir uma solução usando ArcObjects, os blocos de construção
de programação usados pelos próprios desenvolvedores da Esri para produzir os produtos
de desktop do ArcGIS. Com o ArcObjects, é possível customizar a interface do usuário para
incluir comandos e ferramentas específicas que extrapolam a capacidade das ferramentas
9
do ArcGIS prontas para uso ou as modificam para trabalhar de maneira mais focada. A
programação de ArcObjects e personalização de interface estão fora do escopo deste curso.
A customização SIG com ArcObjects pode ser um avanço, e aprender uma linguagem de
script como Python é uma boa maneira de se preparar aprendendo conceitos básicos de
programação.
As ferramentas que você executa no ModelBuilder e Python realmente usam
ArcObjects como base para executar as funções do SIG; No entanto, a vantagem do script
Python com o ArcGIS é que você não precisa aprender toda a lógica ArcObjects por trás das
ferramentas. Seu trabalho é apenas aprender as ferramentas e executá-las na ordem
apropriada para realizar sua tarefa.
Esta primeira lição apresentará conceitos de construção de modelo e redação de
scripts. Começaremos familiarizando-nos apenas com o modo como as ferramentas são
executadas no ArcGIS e como você pode usar essas ferramentas na interface do
ModelBuilder. Em seguida, abordaremos alguns dos princípios básicos do Python e veremos
como as ferramentas podem ser executadas nos scripts.
10
serão utilizadas para o buffer) e uma distância de buffer. Você também é obrigado a
indicar um local para o arquivo de saída (para o novo arquivo com o resultado da
operação de buffer).
• Muitas ferramentas também possuem parâmetros opcionais. Você pode
modificá-los se quiser, mas se não os fornecer, a ferramenta ainda será executada
usando os valores padrão. Para a ferramenta Buffer, os parâmetros opcionais são Side
Type, End Type, Dissolve Type e Dissolve Fields. Parâmetros opcionais são
normalmente especificados após os parâmetros requeridos.
• Clique no botão Show Help no canto inferior direito da ferramenta (se ele
mostrar Hide Help, você já estará visualizando a ajuda). Agora você pode clicar em
qualquer parâmetro na caixa de diálogo para ver uma explicação desse parâmetro na
janela da direita.
• Se você não tiver certeza do significado de um parâmetro, essa é uma boa
maneira de aprender. Por exemplo, com a ajuda ainda aberta, clique na caixa de entrada
Side Type na ferramenta Buffer (exatamente onde diz "FULL"). A Ajuda explica o que
significa o parâmetro Side Type e lista as diferentes opções: FULL, LEFT, RIGHT e
OUTSIDE_ONLY.
Se você precisar de mais ajuda, cada ferramenta é mais amplamente documentada na
Ajuda do ArcGIS Desktop (com exemplos do Python!). Você pode ir diretamente para a ajuda
da ferramenta Buffer clicando no botão Tool Help na caixa de diálogo da ferramenta, mas
você frequentemente desejará acessar essas páginas de ajuda sem abrir a própria
ferramenta. Abaixo estão os passos para fazer isso.
• No menu principal do ArcMap, clique em Help> ArcGIS Desktop Help.
Opcionalmente, para a ajuda mais atualizada, você pode usar a ajuda da Esri na Web.
• Na guia Sumário do sistema de Ajuda, expanda Tools> Tools Reference.
Observe que os tópicos de ajuda nesta seção estão organizados em caixas de
ferramentas e conjuntos de ferramentas, em paralelo ao layout das caixas de ferramentas
do sistema ArcGIS.
• Continue navegando no índice de ajuda para a Analisys toolbox> Proximity
toolset> Buffer. Percorra todo o tópico examinando todas as informações fornecidas
sobre a ferramenta Buffer. Aqui você obtém dicas sobre o que a ferramenta Buffer faz,
como usá-la e como fornecer todos os seus parâmetros.
• Ainda no tópico Buffer, role até a seção marcada Code sample. O tópico de
ajuda de cada ferramenta possui exemplos de programação que mostram maneiras de
executar a ferramenta automaticamente. Esses exemplos são escritos em Python e
serão extremamente valiosos para você conforme você conclui as tarefas neste curso.
Sempre verifique a Referência da Ferramenta de Geoprocessamento na Ajuda se estiver
com problemas para executar uma ferramenta em Python.
11
diretamente do Catálogo e usar a interface gráfica do usuário da ferramenta (GUI,
Graphic Unit Interface) para preencher os parâmetros.
• O ModelBuilder também é um aplicativo GUI no qual você pode configurar
ferramentas para executar em uma determinada sequência, usando a saída de uma
ferramenta como entrada para outra ferramenta.
• Se você estiver familiarizado com a ferramenta e quiser usá-la rapidamente no
ArcMap, talvez prefira a abordagem da janela de comandos Python. Você digita o nome
da ferramenta e os parâmetros necessários em uma janela de comando. Você pode usar
essa janela para executar várias ferramentas em uma linha e declarar variáveis,
efetivamente fazendo scripts simples.
• Se você quiser executar a ferramenta automaticamente, repetidamente ou
como parte de uma sequência lógica maior de ferramentas, poderá executá-la a partir de
um script. Executar uma ferramenta a partir de um script é a opção mais poderosa e
flexível.
Começaremos com o mais simples desses casos, executando uma ferramenta a partir
de sua GUI e indo para o script.
• Clique no botão Add data e navegue até os dados que você acabou de
extrair. Adicione os arquivos Limite e Sedes_Municipais.
• Abra a janela Catálogo, se necessário, e navegue até a ferramenta Buffer,
como fez na seção anterior.
• Clique duas vezes na ferramenta Buffer para abri-la.
• Examine o primeiro parâmetro necessário: Input features. Clique no botão
Browse e navegue até o caminho do conjunto de dados de cidades
C:\SEA5923\Dados\Sedes_Municipais.shp. Observe que, quando você fizer isso, um
caminho será fornecido automaticamente para a classe de feições de saída. O software
faz isso apenas para sua conveniência e você pode alterar o caminho se quiser.
• Uma maneira mais conveniente de fornecer os parâmetros de entrada é
apenas selecionar a camada de mapa de cidades no menu suspenso. Esta lista
suspensa contém automaticamente todas as camadas no seu documento de mapa. No
12
entanto, neste exemplo, navegamos para o caminho dos dados porque é
conceitualmente semelhante a como forneceremos os caminhos na linha de comando e
nos ambientes de script.
• Agora você precisa fornecer o parâmetro Distance para o buffer. Para esta
execução da ferramenta, defina uma unidade linear (Linear Unit) de 5 Km. Quando
executamos a ferramenta a partir dos outros ambientes, aumentaremos ligeiramente a
distância do buffer, por isso sabemos que temos saídas distintas.
• O restante dos parâmetros é opcional. Os parâmetros Side Type e End Type
aplicam-se somente a linhas e polígonos, portanto, eles nem estão disponíveis para
configuração no ambiente da GUI ao trabalhar com pontos das cidades. No entanto,
altere o Dissolve Type para ALL. Isso combina buffers sobrepostos em um único
polígono.
• Clique em OK para executar a ferramenta.
• A ferramenta deve levar apenas alguns segundos para ser concluída. Examine
a saída que aparece no mapa e faça uma “verificação” para se certificar de que os buffers
apareçam ao redor das cidades e eles parecem ter cerca de 5 quilômetros de raio. Você
pode precisar aumentar o zoom para ver os buffers.
• Clique no menu Geoprocessing e clique em Results. Esta janela lista
mensagens sobre sucessos ou falhas de todas as ferramentas recentes que você
executou.
• Expanda a ferramenta Buffer até que você possa ver todas as mensagens. Eles
listam os parâmetros da ferramenta, o tempo de conclusão e quaisquer problemas que
ocorreram durante a execução da ferramenta. (veja a figura) Essas mensagens podem
ser de grande ajuda mais tarde, quando você soluciona problemas de seus scripts
Python. O texto dessas mensagens está disponível se você executar a ferramenta a partir
da GUI, da janela do Python no ArcMap ou de scripts.
13
Um conjunto de ferramentas encadeadas dessa maneira é chamado de modelo. Os
modelos podem ser simples, consistindo em apenas algumas ferramentas, ou complexos,
consistindo em muitas ferramentas e parâmetros e, ocasionalmente, em alguma lógica
iterativa. Seja grande ou pequeno, o benefício de um modelo é que ele resolve um problema
geográfico único que não pode ser resolvido por uma das ferramentas “out-of-the-box”.
No ArcGIS, a modelagem pode ser feita através da interface gráfica do usuário
ModelBuilder (GUI) ou através de código, usando Python. Para manter nossos termos claros,
vamos nos referir a qualquer coisa construída no ModelBuilder como um “modelo” e qualquer
coisa construída através do Python como um “script”. No entanto, é importante lembrar que
ambas as coisas estão fazendo modelagem.
14
seguida pela ferramenta Intersect e, em seguida, pela ferramenta Clip, você pode configurá-
las no ModelBuilder para serem executadas como um processo.
• Crie um novo documento de mapa no ArcMap e adicione os shapefiles
Sedes_Municipais, Rodovias e Limite da pasta de dados que você configurou
anteriormente nesta lição. Salve seu documento de mapa como
C:\SEA5923\Modelos.mxd.
• No ArcGIS, todos os modelos são armazenados em caixas de ferramentas. A
primeira coisa que você precisa fazer é criar uma caixa de ferramentas para armazenar
seu novo modelo. Se a janela Catálogo já não estiver visível, exiba-a clicando no item de
menu Windows> Catalog.
• Na janela Catálogo, expanda os nós até ver as Toolboxes> My Tollboxes.
• Clique com o botão direito em My Toolboxes e clique em New> Toolbox.
Nomeie-o como SEA5923. (O software pode adicionar .tbx, o que é bom)
• Clique com o botão direito do mouse na caixa de ferramentas SEA5923.tbx e
clique em New> Model. Você verá o ModelBuilder aparecer.
• No ModelBuilder, clique em Model> Model Properties.
• Para o Name, digite “Aptidao” e, para o Label, digite “Localizar áreas com
aptidão”. O rótulo é o que todos verão quando abrirem sua ferramenta no catálogo. É por
isso que pode conter espaços. O nome é o que as pessoas usarão se alguma vez
executarem seu modelo a partir do Python. É por isso que não pode conter espaços.
• Clique em OK para descartar a caixa de diálogo Propriedades do modelo.
Agora você tem uma tela em branco na qual você pode arrastar e soltar as
ferramentas. Ao criar um modelo (e ao escrever scripts em Python), é melhor dividir
seu problema em partes gerenciáveis. O problema simples de seleção de “sites”
aqui pode ser considerado como quatro etapas:
• Buffer para as cidades
• Buffer para as estradas
• Intersectar os buffers
• Clipe para a região de limite
Vamos abordar esses itens um de cada vez, começando com o buffer das cidades.
• Com o ModelBuilder ainda aberto, vá para a janela Catálogo e navegue até
Toolboxes > System Toolboxes > Analysis Tools > Proximity.
• Clique na ferramenta Buffer e arraste-a para a tela ModelBuilder. Você verá
uma caixa retangular branca representando a ferramenta de buffer e uma forma oval
branca representando os buffers de saída. Eles estão conectados a uma linha,
mostrando que a ferramenta Buffer sempre produzirá um conjunto de dados de saída.
No ModelBuilder, as ferramentas são representadas com caixas e as variáveis são
representadas com ovais. No momento, a ferramenta Buffer, no centro, é branca
porque você ainda não forneceu os parâmetros necessários. Depois de fazer isso,
a ferramenta e a variável serão preenchidas com cor.
15
• Na janela ModelBuilder, clique duas vezes na caixa Buffer. O diálogo da
ferramenta aqui é o mesmo que se você tivesse aberto o Buffer diretamente do
ArcToolbox. É aqui que você pode fornecer parâmetros para a ferramenta.
• Para Input Features, navegue até o caminho do arquivo shape
Sedes_Municipais. A classe de feições de saída será preenchida automaticamente.
• Para Distance [value or field], insira 5 Kilometer.
• Para Dissolve Type, selecione ALL e clique em OK para fechar a caixa de
diálogo Buffer. Os elementos do modelo (ferramentas e variáveis) devem ser
preenchidos com cor e você deve ver um novo elemento à esquerda da ferramenta que
representa a classe de feições de cidades como entrada.
• Uma parte importante do trabalho com o ModelBuilder é fornecer rótulos claros
para todos os elementos. Dessa forma, se você compartilhar seu modelo, os outros
poderão entender facilmente o que acontecerá quando for executado. Fornecer rótulos
claros também ajuda você a lembrar o que o modelo faz, especialmente se você não
trabalhar com o modelo por algum tempo.
• No ModelBuilder, clique com o botão direito do mouse no elemento
Sedes_Municipais.shp (oval azul, à esquerda) e clique em Rename. Nomeie esse
elemento como "Cidades".
• Clique com o botão direito na ferramenta Buffer (caixa amarelo-laranja, no
centro) e clique em Rename. Nomeie isso "Buffer das cidades".
• Clique com o botão direito do mouse no elemento
Sedes_MuniciapaisBuffer1.shp (oval verde, à direita) e clique em Rename. Nomeie isso
como "Cidades com buffer". Seu modelo deve se parecer com isso.
A aparência do modelo.
• Salve seu modelo (Model> Save). Este é o tipo de atividade em que você
deseja salvar com frequência.
• Pratique o que você acabou de aprender adicionando outra ferramenta Buffer
ao seu modelo. Desta vez, configure a ferramenta para que ela armazene o arquivo
shape Rodovias com 20 km. Lembre-se de definir o tipo Dissolve para ALL e adicionar
rótulos significativos. Seu modelo deve agora se parecer com isso.
16
A aparência do modelo após o passo acima.
• A próxima tarefa é interceptar os buffers. Na lista de caixas de ferramentas da
janela Catálogo, navegue até Analysis Tools> Overlay e arraste a ferramenta Intersect
para o seu modelo. Posicione-o à direita das ferramentas do Buffer existentes.
• Aqui está o momento crucial em que você encadeia as ferramentas, definindo
as saídas de suas ferramentas Buffer como entradas da ferramenta Intersect. Clique na
ferramenta Connect e , em seguida, clique no elemento Cidades com buffer seguido
pelo elemento Intersect. Se você vir um pequeno menu, clique em Input Features para
indicar que as cidades em buffer agem como entradas para a ferramenta Intersect. Uma
seta agora apontará do elemento Cidades com buffer para o elemento Intersect.
• Use o mesmo processo para conectar as Rodovias com buffer ao elemento
Intersect. Novamente, se solicitado, clique em Input Features.
• Renomeie a saída da operação Intersect como "Intersected buffers". Se o texto
for executado em várias linhas, você poderá clicar e arrastar as bordas do elemento para
redimensioná-lo. Você também pode reorganizar os elementos na página da forma que
desejar. Como os modelos podem ficar grandes, o ModelBuilder contém vários botões
de navegação para ampliar e aplicar zoom em toda a extensão do modelo.
Seu modelo deve estar assim:
17
Catálogo, navegue até Analysis Tools> Extract e arraste a ferramenta Clip para o
ModelBuilder. Posicione essa ferramenta à direita de suas ferramentas existentes.
• Use a ferramenta Connect novamente para definir os buffers interceptados
como uma entrada para a ferramenta Clip, escolhendo Input Features quando solicitado.
Observe que, mesmo quando você faz isso, a ferramenta Clip não está pronta para ser
executada (ela ainda é mostrada como um retângulo branco, localizado à direita). Você
precisa fornecer o parâmetro de recorte, que é o contorno para a qual os buffers serão
cortados.
• No ModelBuilder (não na janela Catálogo), clique duas vezes na ferramenta
Clip. Defina o parâmetro navegando até o caminho de Limite.shp e clique em OK para
fechar a caixa de diálogo. Você notará que um oval azul apareceu representando a Clip
Features (Limite).
• Defina rótulos significativos para as ferramentas restantes, conforme mostrado
o exemplo abaixo de como você pode rotular e organizar os elementos do modelo.
18
A saída do modelo no ArcMap.
É isso aí! Você acabou de usar o ModelBuilder para encadear várias ferramentas e
resolver um problema de SIG.
Você pode clicar duas vezes nesse modelo a qualquer momento na janela Catálogo e
executá-lo como faria com uma ferramenta. Se você fizer isso, notará que o modelo não
possui parâmetros; você não pode alterar a distância do buffer ou os recursos de entrada. A
verdade é que nosso modelo é útil para resolver esse problema específico de seleção de
sites com esses conjuntos de dados específicos, mas não é muito flexível. Na próxima seção
da lição, tornaremos esse modelo mais versátil, configurando algumas das variáveis como
parâmetros de entrada e saída.
Parâmetros do modelo
A maioria das ferramentas, modelos e scripts criados com o ArcGIS possuem
parâmetros. Parâmetros de entrada são valores com os quais a ferramenta (ou modelo ou
script) inicia seu trabalho e os parâmetros de saída representam o que a ferramenta fornece
como resultado após o término de sua execução.
Uma ferramenta, modelo ou script sem parâmetros só serve em um cenário específico.
Considere o modelo que você acabou de criar que usava as ferramentas Buffer, Intersect e
Clip. Esse modelo foi codificado para usar os arquivos shapefiles Sedes_Municipais,
Rodovias e Limite e gerar um shapefile chamado AreaAptidao. Em outras palavras, se você
quisesse executar o modelo com outros conjuntos de dados, teria que abrir o ModelBuilder,
clicar duas vezes em cada elemento (Cidades, Rodovias, Limite e Área de Aptidão) e alterar
19
os caminhos que foram gravados diretamente no modelo. Você teria que seguir um processo
semelhante se também quisesse alterar as distâncias de buffer, já que elas eram codificadas
a 5 quilômetros.
Vamos modificar esse modelo para usar alguns parâmetros, para que você possa
executá-lo facilmente com diferentes conjuntos de dados e distâncias de buffer.
• Se ainda não estiver aberto, abra o documento do mapa
C:\SEA5923\Modelos.mxd no ArcMap.
• Na janela Catalog, encontre o modelo criado na lição anterior, que deve estar
em Toolboxes> My Toolboxes> SEA5923> Localizar áreas de aptidão.
• Clique com o botão direito no modelo Localizar áreas de aptidão e clique em
Copy. Agora clique com o botão direito do mouse na caixa de ferramentas SEA5923 e
clique em Paste. Isso cria uma nova cópia do seu modelo com a qual você pode trabalhar
para criar parâmetros de modelo. Usando uma cópia do modelo como este permite que
você facilmente comece de novo se você cometer um erro.
• Renomeie a cópia do seu modelo Localizar áreas de aptidão com
parâmetros ou algo similar.
• Na sua caixa de ferramentas SEA5923, clique com o botão direito do mouse
em Localizar áreas de aptidão com parâmetros e clique em Edit. Você verá o modelo
aparecer no ModelBuilder.
• Clique com o botão direito do mouse no elemento Cidades (deve ser um oval
azul) e clique em Model Parameter. Isso significa que quem quer que execute o modelo
deve especificar o conjunto de dados de cidade a ser usado antes que o modelo possa
ser executado.
• Mesmo que você tenha "parametrizado" as cidades, seu modelo ainda usa o
conjunto de dados C:\SEA5923\Dados\Sedes_Municipais.shp. Isso não fará muito
sentido se você compartilhar seu modelo ou caixa de ferramentas com outras pessoas,
pois elas podem não ter o mesmo arquivo shape e, mesmo se o tenham, provavelmente
não estarão no mesmo caminho em suas máquinas.
• Para remover o conjunto de dados padrão, clique duas vezes no elemento
Cidades, exclua o caminho e clique em OK. Alguns dos elementos do seu modelo podem
ficar brancos. Isso significa que um valor deve ser fornecido antes que o modelo possa
ser executado com sucesso.
• Agora você precisa criar um parâmetro para a distância do buffer a ser criado
em torno das cidades. Clique com o botão direito do mouse no elemento que você
chamou de "Buffer das cidades" e clique em Make Variable> From Parameter>
Distance [value or field].
• A etapa anterior criou um novo elemento Distance. Renomeie este elemento
para "Distância" e torne-o um parâmetro de modelo. (Revise as etapas acima se não tiver
certeza sobre como renomear um elemento ou torná-lo um parâmetro de modelo.) Para
este elemento, você pode deixar o padrão em 5 quilômetros.
• Repetindo o que você aprendeu acima, altere o elemento Rodovias, torne-o um
parâmetro de modelo e remova o valor padrão.
• Repetindo o que você aprendeu acima, crie um parâmetro para a distância do
buffer de rodovias. Deixe o padrão em 5 quilômetros.
20
• Repetindo o que você aprendeu acima, altere o elemento Limite, torne-o um
parâmetro de modelo e remova o valor padrão. Seu modelo deve ficar assim (observe
os cinco parâmetros indicados por "P" s):
O modelo "Localizar áreas de aptidão com parâmetros " seguindo o passo acima, e
mostrando cinco parâmetros.
• Salve seu modelo e feche o ModelBuilder.
• Clique duas vezes no modelo SEA5923> Localizar áreas de aptidão com
parâmetros e examine o diálogo da ferramenta. Deve ser semelhante a isto:
21
• Teste seu modelo fornecendo os arquivos Sedes_Municipais, Rodovias e
Limite para os parâmetros do modelo. Se você quiser, você pode tentar mudar a distância
do buffer.
Note que às vezes o resultado não se adiciona ao display como deveria. Você deve
ser capaz de adicioná-lo ao display usando o botão Add Data e navegando até o
local AreaAptidao.shp.
O exercício acima demonstrou como você pode expor valores como parâmetros
usando o ModelBuilder. Você precisa decidir quais valores deseja que o usuário possa
alterar e designar esses como parâmetros. Quando você escreve scripts em Python, também
é necessário identificar e expor parâmetros de maneira semelhante.
22
o curso. Alguns dos conceitos neles são mais fáceis de entender uma vez que você tenha
trabalhado com geoprocessamento por um tempo.
Um tour rápido pelo gerenciamento de dados intermediários
(http://desktop.arcgis.com/en/arcmap/latest/analyze/modelbuilder/a-quick-tour-of-managing-
intermediate-data.htm)
Usando os ambientes de espaço de trabalho atual e de rascunho
(http://desktop.arcgis.com/en/arcmap/latest/analyze/executing-tools/using-the-current-and-scratch-
workspace-environments.htm)
Gerenciando dados intermediários (scratch) no modelo compartilhado e nas
ferramentas de script (http://desktop.arcgis.com/en/arcmap/latest/analyze/sharing-
workflows/managing-intermediate-data-in-models-and-scripts.htm)
Looping no ModelBuilder
Loop, ou iteração, é o ato de repetir um processo. Um dos principais benefícios dos
computadores é sua capacidade de repetir rapidamente tarefas que, de outra forma, seriam
rotineiras, incômodas ou passíveis de erros para um ser humano repetir e gravar. O looping
é um conceito-chave em programação de computadores e você o usará com frequência ao
escrever scripts em Python para esse curso.
O ModelBuilder contém um número de elementos chamados Iteradores que podem
fazer looping de várias maneiras. Os nomes desses iteradores, como For e While, na
verdade, imitam os tipos de loop que você pode programar em Python ou em outras
linguagens. Neste curso, vamos nos concentrar em aprender iteração em Python, o que
pode ser tão fácil quanto aprender como usar um iterador ModelBuilder.
Para dar uma olhada em como a iteração funciona no ModelBuilder, você pode visitar
o manual de ajuda do ArcGIS Desktop para iteração de modelo
(http://desktop.arcgis.com/en/arcmap/latest/analyze/modelbuilder/a-quick-tour-of-using-
iterators-for-iteration-looping-.htm). Se você tiver problemas para entender o loop em lições
posteriores, o ModelBuilder pode ser um bom ambiente para visualizar o que um loop faz.
Você pode voltar e visitar a ajuda conforme necessário.
Leituras
Leia Zandbergen Chapter 2.1 - 2.9 para reforçar o que você aprendeu sobre
geoprocessamento e ModelBuilder.
23
• Na barra de ferramentas Standard, clique no botão Python Windows.
Quando a janela aparecer, arraste-a para o lado ou para baixo da tela para encaixá-la.
• Digite o seguinte na janela do Python (Não digite o >>>. Eles são incluídos
apenas para mostrar onde as novas linhas começam na janela do Python.)
>>> import arcpy
>>> arcpy.Buffer_analysis ("Sedes_Municipais", "Cidades_buffer_15km",
"15 kilometers", "", "", "ALL")
• Amplie e examine os buffers criados.
Você acabou de executar seu primeiro comando de Python. Você não precisa
entender tudo sobre o código que escreveu nesta janela, mas aqui estão algumas
coisas importantes a serem observadas.
A primeira linha do script “Import arcpy” informa ao interpretador Python (que foi
instalado quando você instalou o ArcGIS) que você irá trabalhar com algumas funções e
ferramentas especiais de script incluídas no ArcGIS. Sem essa linha de código, o Python
não sabe nada sobre o ArcGIS, então você o colocará no topo de todos os códigos
relacionados ao ArcGIS que você escreverá nesta classe. Você tecnicamente não precisa
desta linha quando você trabalha com a janela do Python no ArcMap porque o arcpy já é
importado, mas eu queria mostrar esse padrão antes; você vai usá-lo em todos os scripts
que você escrever fora da janela do Python.
A segunda linha do script, na verdade, executa a ferramenta. Você pode digitar arcpy,
acompanhado de um ponto, além de qualquer nome de ferramenta do ArcGIS para executá-
la no Python. Observe aqui que você também coloca um underscore seguido pelo nome da
caixa de ferramentas que inclui a ferramenta que irá utilizar. Isso é necessário porque
algumas ferramentas em diferentes caixas de ferramentas realmente têm o mesmo nome
(como o Clip, que é uma ferramenta para recortar vetores na caixa de ferramentas Analysis
ou ferramenta para recorte de rasters na caixa de ferramentas Data Management).
Depois de digitar arcpy.Buffer_analysis, você digitou todos os parâmetros para a
ferramenta. Cada parâmetro foi separado por uma vírgula e toda a lista de parâmetros foi
colocada entre parênteses. Acostume-se com esse padrão, já que você o seguirá com todas
as ferramentas executadas neste curso.
Nesse código, também fornecemos alguns parâmetros opcionais, deixando aspas
vazias onde queríamos obter os valores padrão e truncando a lista de parâmetros no
parâmetro opcional final que queríamos definir.
Como você conhece a sintaxe ou estrutura dos parâmetros a serem inseridos? Por
exemplo, para a distância do buffer, você deve inserir 15KILOMETERS, '15Kilometers', 15
Km ou '15 kilometers'? A melhor maneira de responder a perguntas como essas é retornar
ao tópico da ajuda de referência da ferramenta Geoprocessing para a ferramenta Buffer.
Todos os tópicos nesta seção de referência possuem uma seção de uso e exemplo de linha
de comando para ajudá-lo a entender como estruturar os parâmetros. Parâmetros opcionais
são colocados entre chaves, enquanto os parâmetros necessários não são. Do exemplo
neste tópico, você pode ver que a distância do buffer deve ser especificada como '15
kilometers'. Como há um espaço nesse texto ou string, você precisa cercá-lo com aspas.
Você deve ter notado que a janela do Python ajuda a mostrar diferentes opções que
você pode digitar para cada parâmetro. Isso é chamado de autocompletar, e pode ser muito
útil se você estiver tentando executar uma ferramenta pela primeira vez e não souber
exatamente como digitar os parâmetros.
24
Existem algumas diferenças entre escrever código na janela do Python e escrever
código em algum outro programa, como o Notepad ou o Python Scripter. Na janela do
Python, você pode fazer referência a camadas no documento do mapa apenas por seus
nomes, em vez de seus caminhos de arquivo. Assim, conseguimos digitar
"Sedes_Municipais" em vez de algo como "C:\\SEA5923\\Dados\\Sedes_Municipais.shp".
Também conseguimos criar o nome de uma nova camada "Cidades_buffer_15km" e incluí-
la no mapa por padrão após a execução do código. Se você for usar seu código fora da
janela do Python, certifique-se de usar os caminhos completos.
Quando você escreve scripts mais complexos, será útil usar um ambiente de
desenvolvimento integrado (IDE), ou seja, um programa projetado especificamente para
ajudá-lo a escrever e testar o código Python. Mais adiante neste curso, exploraremos o IDE
do PythonWin.
Anteriormente nesta lição você viu como as ferramentas podem ser encadeadas para
resolver um problema usando o ModelBuilder. O mesmo pode ser feito em Python, mas será
necessário um pouco de trabalho para chegar a esse ponto. Por esse motivo, passaremos
o restante da Aula 1 cobrindo alguns dos princípios básicos do Python.
Leituras
Reserve alguns minutos para ler o capítulo 3 de Zandbergen, um capítulo relativamente
curto, onde ele explica a janela do Python e algumas coisas que você pode fazer com ela.
O que é o Python?
Python é uma linguagem usada para automatizar tarefas de computação por meio de
programas chamados scripts. Na introdução desta lição, você aprendeu que a automação
torna o trabalho mais fácil, mais rápido e mais preciso. Isso se aplica ao SIG e muitas outras
áreas da ciência da computação. O aprendizado de Python fará de você um analista GIS
mais eficaz, mas a programação em Python é uma habilidade técnica que pode ser benéfica
para você mesmo fora do campo de SIG.
O Python é uma boa linguagem para iniciar a programação. O Python é uma linguagem
de alto nível, o que significa que você não precisa entender como os computadores
funcionam para usá-la. A sintaxe do Python (como as instruções de código são construídas)
é relativamente simples de ler e entender. Por fim, o Python requer muito pouco para colocar
um programa em funcionamento.
O Python é uma linguagem de código aberto e não há custos para usá-la ou implantar
programas nela. O Python pode ser executado nos sistemas operacionais Windows, Linux
e Unix.
No ArcGIS, o Python pode ser usado praticamente como um atalho, o que significa que
você pode usá-lo para executar facilmente ferramentas de geoprocessamento como a
ferramenta Buffer com a qual trabalhamos. Você poderia codificar toda a lógica do buffer,
usando uma programação mais detalhada com o ArcObjects, mas isso seria demorado e
desnecessário na maioria dos cenários; sendo mais fácil apenas chamar a ferramenta Buffer
de um script Python usando uma linha de código.
25
Além da ajuda ESRI que descreve todos os parâmetros de uma função e como acessá-
los a partir do Python, você também pode obter a sintaxe Python (a estrutura da linguagem)
para uma ferramenta da seguinte forma:
• Execute a ferramenta interativamente (por exemplo, buffer) com seus dados de
entrada, dados de saída e quaisquer outros parâmetros relevantes (por exemplo,
distância ao buffer)
• Vá para a janela Geoprocessing -> Results e clique com o botão direito do
mouse na execução da ferramenta concluída.
• Escolha "Copy as Python Snippet"
• Cole o código no PythonWin ou na janela de código Python para ver como você
codificaria a mesma operação que você acabou de executar no Desktop no Python.
Instalando o PythonWin
Se você instalou uma versão do ArcGIS, você já deve ter o Python em seu computador,
normalmente em uma pasta chamada algo como C:\Python27\ArcGIS10.x\. Você pode
escrever código Python a qualquer momento no Bloco de Notas ou em outros editores e
salvá-lo como um arquivo .py, mas é necessário ter o Python instalado para que seu
computador possa entender e executar o programa.
Neste curso, estaremos trabalhando com o Python versão 2.7.x. Se você verificar a
página de download do Python em sua home page em www.python.org (novamente, você
não precisará baixar o Python, apenas dê uma olhada!), Você verá que existem versões
realmente superiores do Python acessível. As versões 3 e superiores do Python contêm
algumas mudanças importantes que levaram algum tempo para a comunidade de usuários
do Python e a ESRI adotarem.
O Python vem com um editor padrão simples chamado IDLE; no entanto, neste curso,
você usará o ambiente de desenvolvimento integrado (IDE) do PythonWin para ajudá-lo a
escrever código.
O PythonWin é gratuito, tem recursos básicos de depuração. Nós aqui iremos baixar e
instalar a versão do PythonWin do repositório PythonWin GitHub em
https://github.com/mhammond/pywin32/releases . É importante que você use a versão
"win32" para Python 2.7 e não os executáveis “amd64" que são para instalar a versão de 64
bits do PythonWin, que é compatível apenas com o ArcGIS for Server, não com o ArcGIS
for Desktop.
Por favor siga as instruções abaixo:
• Baixe o arquivo de instalação do PythonWin neste link:
https://github.com/mhammond/pywin32/releases/download/b224/pywin32-224.win32-
py2.7.exe
• Inicie a instalação iniciando o arquivo baixado pywin32-2xx.win32-py2.7.exe.
(Se você estiver usando o Windows Vista ou o Windows 7, clique com o botão direito do
mouse nesse arquivo e escolha Executar como administrador e, quando solicitado,
escolha Permitir que ele seja executado.)
26
• Clique em Avançar através do assistente para instalar o PythonWin.
• O PythonWin não coloca um atalho do Windows em lugar algum, então você
pode fazer um você mesmo. Quando a instalação estiver concluída, use Meu
Computador (ou "Computador") para procurar o local onde você instalou o PythonWin.
Provavelmente está em C:\Python27\ArcGIS10.x\Lib\site-packages\pythonwin.
• Clique com o botão direito do mouse no item PythonWin.exe e clique em Criar
atalho. Você deve ver um atalho do Windows aparecer imediatamente abaixo do item
PythonWin.
• Arraste e solte o atalho na sua área de trabalho ou onde quer que você queira
colocá-lo.
No Windows Vista ou Windows 7, se você vir mensagens de erro durante a instalação,
é provável que você não tenha executado a instalação como um Administrador. Ao iniciar a
instalação, clique com o botão direito do mouse e escolha Executar como administrador.
Explorando o PythonWin
Aqui está uma breve explicação das principais partes do PythonWin. Antes de começar
a ler, abra o PythonWin para que você possa acompanhar.
Quando o PythonWin abrir, você verá o que é conhecido como a Janela Interativa. Você
pode digitar uma linha de Python no prompt >>> e ela imediatamente executará e imprimirá
o resultado, se houver um resultado imprimível. A Janela Interativa pode ser um bom lugar
para praticar com o Python neste curso, e sempre que você vir algum código Python ao lado
do prompt >>> nos materiais da lição, isso significa que você pode digitá-lo na Janela
Interativa para acompanhar. Desta forma, a Janela Interativa é muito semelhante à janela
do Python no ArcGIS.
27
contém ferramentas para carregar, executar e salvar scripts. Esta barra de ferramentas
é visível por padrão. Observe os botões Undo / Redo , que podem ser úteis para
você como programador se você começar a codificar algo e perceber que percorreu o
caminho errado, ou se você excluir uma linha de código e quiser recuperá-la. Observe
também o botão Execute , que parece uma pequena pessoa correndo. Essa é uma boa
maneira de testar seus scripts sem precisar clicar duas vezes no arquivo no Windows
Explorer.
A barra de ferramentas de Debugging
contém ferramentas para revisar cuidadosamente seu código linha por linha para
ajudá-lo a detectar erros. Esta barra de ferramentas é visível clicando em View > Toolbar >
Debugging. A barra de ferramentas Depuração é extremamente valiosa para você como
programador e você aprenderá a usá-la posteriormente neste curso. Essa barra de
ferramentas é um dos principais motivos para usar um Ambiente de Desenvolvimento
Integrado (IDE) em vez de gravar seu código em um editor de texto simples como o Bloco
de Notas.
28
Você acabou de criar ou declarou uma variável x e definir seu valor como 2. Em
algumas linguagens de programação fortemente tipificadas, como Java, você precisaria
informar ao programa que estava criando uma variável numérica, mas o Python assume isso
quando você digita o 2.
Quando você aperta Enter, nada acontece, mas o programa agora tem essa variável
na memória. Para provar isso, digite:
>>> x + 3
Você vê a resposta desta expressão matemática, 5, aparecer imediatamente na Janela
Interativa, provando que sua variável foi lembrada e usada.
Você também pode usar o comando print para gravar os resultados das operações.
Nós vamos usar muito isso quando praticar e testar código.
>>> print (x + 3)
5
Variáveis também podem representar palavras ou cadeias de caracteres, como são
referidas pelos programadores. Tente digitá-lo na janela interativa:
>>> meuTime = "Time do bairro"
>>> print (meuTime)
Time do bairro
Neste exemplo, as aspas informam ao Python que você está declarando uma variável
de string. Python é uma linguagem poderosa para trabalhar com strings. Um exemplo muito
simples de manipulação de strings é adicionar ou concatenar duas strings, desta forma:
>>> string1 = "Nós Somos"
>>> string2 = "EESC USP!"
>>> print (string1 + string2)
Nós somos EESC USP!
Você pode incluir um número em uma variável de string colocando-o entre aspas, mas
depois deve tratá-lo como uma string; você não pode tratá-lo como um número. Por exemplo,
isso resulta em um erro:
>>> meuValor = "3"
>>> print (meuValor + 2)
Nestes exemplos você viu o uso do sinal = para atribuir o valor da variável. Você
sempre pode reatribuir a variável. Por exemplo:
>>> x = 5
>>> x = x - 2
>>> print (x)
3
Ao nomear suas variáveis, as dicas a seguir ajudarão você a evitar erros.
• Nomes de variáveis diferenciam maiúsculas de minúsculas. minhaVariavel é
uma variável diferente do MinhaVariavel.
29
• Nomes de variáveis não podem conter espaços.
• Nomes variáveis não podem começar com um número.
• Uma prática recomendada para variáveis Python é nomear a variável
começando com uma letra minúscula e, em seguida, começar cada palavra subseqüente
com uma letra maiúscula. Isso às vezes é conhecido como invólucro de camelo. Por
exemplo: minhaVariavel, minhaSegundaVariavel, tabelaRodovias, campoBuffer1, etc.
• As variáveis não podem ser nenhuma das palavras reservadas especiais do
Python, como "import" ou "print".
Torne os nomes das variáveis significativos para que os outros possam ler facilmente
o seu código. Isso também ajudará você a ler seu código e evitar cometer erros.
Você terá muita experiência trabalhando com variáveis ao longo deste curso e
aprenderá mais em lições futuras.
Leituras
Leia o capítulo 4.5 de Zandbergen (Variables and naming).
O Capítulo 4 aborda os fundamentos da sintaxe Python, loops, strings e outras coisas
que veremos mais detalhadamente adiante, mas sinta-se à vontade para ler um pouco agora
se tiver tempo.
30
• Coloque um pouco de manteiga de amendoim na faca.
• etc.
• etc.
Se fôssemos escrever o programa em uma linguagem orientada a objeto, poderia ser
assim:
• mySandwich = Sandwich.Make
• mySandwich.pão = Trigo
• mySandwich.Adiciona (manteiga de amendoim)
• mySandwich.Adiciona (geleia)
No exemplo orientado a objetos, a maior parte das etapas foi eliminada. O objeto
sanduíche "sabe como" se construir, dado apenas algumas informações. Esse é um recurso
importante de linguagens orientadas a objetos conhecidas como encapsulamento.
Observe que você pode definir as propriedades do sanduíche (como o tipo de pão) e
executar métodos (lembre-se de que são ações) no sanduíche, como adicionar a manteiga
de amendoim e a geleia.
Classes
A razão pela qual é tão fácil "fazer um sanduíche" em uma linguagem orientada a
objetos é que algum programador, em algum lugar, já fez o trabalho para definir o que é um
sanduíche e o que você pode fazer com ele. Ele ou ela fez isso usando uma Classe. Uma
classe define como criar um objeto, as propriedades e os métodos disponíveis para esse
objeto, como as propriedades são definidas e usadas e o que cada método faz.
Uma classe pode ser considerada como uma planta para criar objetos. O blueprint
determina quais propriedades e métodos um objeto dessa classe terá. Uma analogia comum
é a de uma fábrica de automóveis. Uma fábrica de carros produz milhares de carros do
mesmo modelo, todos construídos no mesmo modelo básico. Da mesma forma, uma classe
produz objetos que possuem as mesmas propriedades e métodos predefinidos.
Em Python, as classes são agrupadas em módulos. Você importa módulos em seu
código para dizer ao seu programa com quais objetos você estará trabalhando. Você mesmo
pode escrever módulos, mas provavelmente você os importará de outras partes ou pacotes
de software. Por exemplo, a primeira linha da maioria dos scripts que você escreve neste
curso será:
import arcpy
Aqui você está usando a palavra-chave import para dizer ao seu script que você estará
trabalhando com o módulo arcpy, que é fornecido como parte do ArcGIS. Depois de importar
este módulo, você pode criar objetos que alavancam o ArcGIS em seus scripts.
Outros módulos que você pode importar neste curso são OS (permite que você trabalhe
com o sistema operacional), Randon (permite a geração de números aleatórios), CSV
(permite a leitura e gravação de arquivos de planilha em formato de valor separado por
vírgula), e Math (permite que você trabalhe com operações matemáticas avançadas). Esses
31
módulos estão incluídos no Python, mas não são importados por padrão. Uma prática
recomendada para manter seus scripts rápidos é importar apenas os módulos necessários
para esse script específico. Por exemplo, embora possa não causar erros no seu script, você
não incluiria a importação arcpy em um script que não requer nenhuma função do ArcGIS.
Leituras
Leia o capítulo 5.8 (Classes) de Zandbergen para mais informações sobre classes.
Herança
Outra característica importante das linguagens orientadas a objetos é a herança. As
classes são organizadas em um relacionamento hierárquico, de modo que cada classe herda
suas propriedades e métodos da classe acima na hierarquia (sua classe pai ou superclasse).
Uma classe também passa suas propriedades e métodos para a classe abaixo dela (sua
classe filha ou subclasse).
Uma analogia do mundo real envolve a classificação de espécies animais. Como
espécie, temos muitas características exclusivas dos seres humanos. No entanto, também
herdamos muitas características de classes superiores na hierarquia de classes. Temos
algumas características como resultado de sermos vertebrados. Temos outras
características como resultado de sermos mamíferos. Para ilustrar o ponto, pense na
capacidade dos humanos de correr. Nossos corpos respondem ao nosso comando de correr
não porque pertencemos à classe "humana", mas porque herdamos essa característica de
alguma classe superior na hierarquia de classes.
De volta ao contexto de programação, a lição a ser aprendida é que vale a pena saber
onde uma classe se encaixa na hierarquia de classes. Sem essa informação, você não terá
conhecimento de todas as operações disponíveis para você. Essas informações sobre
heranças podem ser encontradas em pôsteres informativos chamados diagramas de
modelos de objetos.
Aqui está um exemplo de uma parte do diagrama de modelo de objeto para o ArcGIS
Python Geoprocessor em 10.x.
32
Diagrama de modelo de objeto para o ArcGIS Python Geoprocessor
Dê uma olhada na caixa verde intitulada FeatureClass Properties e observe na coluna
do meio, segundo a partir do topo, Propriedades do Dataset. Isso ocorre porque
FeatureClass herda todas as propriedades do DataSet. Portanto, quaisquer propriedades
em um objeto DataSet, como Extent ou SpatialReference, também podem ser obtidas se
você criar um objeto FeatureClass. Além de todas as propriedades que ele herda do Dataset,
o FeatureClass tem suas próprias propriedades especializadas, como FeatureType e
ShapeType (na caixa superior, na coluna da esquerda).
Sintaxe do Python
Toda linguagem de programação tem regras sobre capitalização, espaço em branco,
como separar linhas de código e procedimentos, e assim por diante. Aqui estão algumas
regras básicas de sintaxe para lembrar do Python:
• O Python diferencia maiúsculas de minúsculas nos nomes de variáveis e
palavras reservadas. Isso significa que é importante se você usa letras maiúsculas ou
minúsculas. A minúscula "print" é uma palavra reservada no Python que imprimirá um
valor, enquanto "Print" não é reconhecido pelo Python e retornará um erro. Da mesma
33
forma, o módulo arcpy é muito sensível a sintaxe e retornará um erro se você tentar
executar uma ferramenta sem capitalizar o nome da ferramenta.
• Você finaliza uma instrução Python pressionando Enter e iniciando literalmente
uma nova linha. (Em algumas outras linguagens, um caractere especial, como um ponto-
e-vírgula, indica o final de uma instrução.) Não há problema em adicionar linhas vazias
para dividir seu código em seções lógicas.
• Se você tiver uma instrução longa que deseja exibir em várias linhas para
facilitar a leitura, será necessário usar um caractere de continuação de linha, que em
Python é uma barra invertida (\). Você pode continuar digitando na linha abaixo e o
Python interpretará a sequência de linhas como uma instrução. Uma exceção é se você
estiver no meio de parênteses () ou colchetes [], o Python entende que você está
continuando as linhas e que nenhuma barra invertida é necessária.
• A indentação é necessária no Python para agrupar logicamente determinadas
linhas ou blocos de código. Você deve recuar seu código em quatro espaços dentro de
loops, if / then statements e try / except statements. Na maioria das linguagens de
programação, os desenvolvedores são encorajados a usar o recuo para agrupar
logicamente blocos de código; no entanto, no Python, o recuo dessas construções de
linguagem não é apenas incentivado, mas necessário. Embora esse requisito possa
parecer pesado, ele resulta em maior legibilidade.
• Você pode adicionar um comentário ao seu código iniciando a linha com um
sinal de libra (#). Comentários são linhas que você inclui para explicar o que o código
está fazendo. Comentários são ignorados pelo Python quando ele executa o script, para
que você possa adicioná-los em qualquer lugar em seu código sem se preocupar com o
efeito deles. Os comentários ajudam outras pessoas que podem ter que trabalhar com
seu código no futuro; e eles podem até ajudá-lo a lembrar o que o código faz no caso de
você precisar alterá-lo.
34
10 referenciaEspacial = desc.spatialReference
11
12 # Retorna o nome da referência espacial
13 print (referenciaEspacial.Name)
Isso pode parecer intimidador no início, então vamos ver o que está acontecendo neste
script, linha por linha.
Nas linhas 1, 2, 8 e 12 são utilizados comentários que tentam elucidar as operações
que seguem após os comentários, é importante que o analista se acostume em comentar o
código de forma que outros usuários possam ter o real entendimento do que o script está
realizando.
Na linha 4 importamos o módulo arcpy, de forma que o IDE tenha acesso às classes
de códigos das ferramentas de geoprocessamento da ESRI.
Na linha 6 é criada uma variável chamada featureClass, do tipo string, pois recebe um
valor entre aspas, que armazena o endereço de uma feature class (Limite) armazenada
dentro de um geodatabase (BaseDados.gdb).
Na linha 9, nós realmente chamamos um método do arcpy. O método Describe nos
devolve um objeto de descrição da feature class. Nós mencionamos no material do curso
que tudo em Python é um objeto. Objetos têm propriedades que os descrevem e métodos
que são coisas que eles podem fazer.
Se você quiser aprender mais sobre o objeto de descrição. Você pode procurar na
ajuda da ESRI.
Em nosso caso, o objeto de descrição terá uma referência espacial. Agora, antes de
sairmos da linha 9, precisamos ter atenção aos parênteses. Então, quando você chama o
método arcpy.Describe. você precisa colocar algo dentro desses parênteses, que é o
caminho da classe de feições que você deseja descrever. Agora não precisamos digitar o
caminho completo novamente porque criamos uma variável anteriormente para representar
isso. Então é aqui que você pode colocar o nome da variável da classe de feição e o Python
lerá como o caminho real.
Então, depois da linha 9, temos um objeto de descrição. Esse objeto descrito possui
uma propriedade que é a referência espacial. Então, na linha 10, é isso que conseguimos.
"desc" é o nome do nosso objeto de descrição e .spatialReference nos fornece um objeto de
referência espacial.
Agora não podemos imprimir um objeto, se você tentar imprimir um objeto na janela
interativa, você vai ter um monte de texto que é difícil de entender, então nós realmente
precisamos obter uma propriedade fora deste objeto de referência espacial e esta
propriedade é o nome da referência espacial. Então é por isso que na linha 13 nós usamos
spatialRef.name.
A essa altura, fomos longe o suficiente para chegarmos a uma string,
referenciaEspacial.name apenas retorna uma string com a referência espacial e é imprimível
na janela interativa. Como resultado obtemos: “GCS_SIRGAS_2000”.
Mais uma vez, observe que:
• Um comentário começa o script para explicar o que vai acontecer.
35
• A diferenciação de maiúsculas e minúsculas é aplicada no código. "import" é
tudo em minúsculas. Então é "imprimir". O nome do módulo "arcpy" é sempre referido
como "arcpy", não "ARCPY" ou "Arcpy". Da mesma forma, "Describe" é capitalizado em
arcpy.Describe.
• Os nomes das variáveis featureClass, desc e referenciaEspacial que o
programador atribuiu são curtos, mas intuitivos. Ao olhar para o nome da variável, você
pode adivinhar rapidamente o que ela representa.
• O script cria objetos e usa uma combinação de propriedades e métodos nesses
objetos para realizar o trabalho. É assim que funciona a programação orientada a
objetos.
Tentando o exemplo por si mesmo
A melhor maneira de se familiarizar com uma nova linguagem de programação é
examinar o código de exemplo e praticar com você mesmo. Veja se você pode modificar o
script acima para relatar a referência espacial de uma classe de feições existente em seu
computador. No exemplo, a classe de feições está em um arquivo geodatabase; você
precisará modificar a estrutura do caminho featureClass se estiver usando um shapefile (por
exemplo, você colocará .shp no final do nome do arquivo e não terá .gdb no caminho).
Siga este padrão para experimentar o exemplo:
• Abra o PythonWin e clique em File> New.
• Escolha Python script e clique em OK.
• Escreva o código acima e modifique-o para ajustar seus dados (mude o
caminho se for necessário).
• Salve seu script como um arquivo .py.
• Clique no botão Execute para executar o script. Certifique-se de que a Janela
Interativa esteja visível quando você fizer isso, porque é onde você verá a saída da
palavra-chave de impressão.
Leituras
Se você é novo em script Python, pode ser útil ver os conceitos de outro ponto de vista.
Leia as partes dos capítulos 4 e 5 de Zandbergen. Esta será uma introdução valiosa
ao Python no ArcGIS, sobre como trabalhar com ferramentas e caixas de ferramentas e
também sobre alguns conceitos que serão revisitados posteriormente.
O Capítulo 4 trata dos fundamentos do Python. Vamos precisar de alguns deles para
começar e vamos revisitar este capítulo a frente. Por enquanto, leia as seções 4.1-4.7
revisando o que lemos em 4.5 anteriormente.
O Capítulo 5 fala sobre o trabalho com o arcpy e suas funções - leia as seções 5.1-5.6.
36
como 0. Esse tipo de operação de “álgebra de mapa” é comum em seleção de áreas e outros
cenários de SIG.
Algo que você pode não reconhecer no script abaixo é a expressão Raster (inRaster).
Esta função apenas diz ao ArcGIS que ele precisa tratar sua variável inRaster como um
conjunto de dados raster para que você possa executar a álgebra de mapa a partir dela. Se
você não fizer isso, o script tratará inRaster como apenas uma sequência literal de caracteres
(o caminho) em vez de um conjunto de dados raster.
37
• Você forneceu os caminhos corretos de entrada e saída.
• O nome do caminho contém barras (/) ou barras invertidas duplas (\\), não
barras invertidas simples (\).
• Você tem o Spatial Analyst Extension instalado e habilitado. Para verificar isso,
abra o ArcMap, clique em Cutomize > Extensions... e verifique se Spatial Analyst está
marcado.
• Você não tem nenhum dos conjuntos de dados abertos no ArcMap.
• Os dados de saída ainda não existem. Se você quiser sobrescrever a saída,
você precisa adicionar a linha arcpy.env.overwriteOutput = True. Esta linha pode ser
colocada imediatamente após a importação do módulo arcpy.
Você pode experimentar esse script usando valores diferentes na expressão de álgebra
do mapa (tente 1000 por exemplo).
Leituras
Leia as seções do Capítulo 5 que falam sobre variáveis de ambiente e licenças (5.9 e
5.11) que abordamos nesta parte da lição.
38
6
7 try:
8 # inserção dos parâmetros
9 entrada = arcpy.GetParameterAsText(0)
10 saida = arcpy.GetParameterAsText(1)
11 distanciaBuffer = arcpy.GetParameterAsText(2)
12
13 # execução da ferramenta
14 arcpy.Buffer_analysis(entrada, saida, distanciaBuffer)
15
16 # Mensagem de sucesso
17 arcpy.AddMessage("Tudo certo!")
18
19 except:
20 # Mensaem de erro
21 arcpy.AddError("Não foi possível completar o buffer")
22
23 # Adiciona mensagens fornecidas da própria ferramenta
24 arcpy.AddMessage(arcpy.GetMessages())
Novamente, examine o código acima linha por linha e descubra o máximo possível
sobre o que o código faz. Se necessário escreva notas ao lado de cada linha. Aqui estão
alguns dos principais pontos a serem entendidos:
• GetParameterAsText() é uma função do módulo arcpy. Observe que é
necessário um inteiro (0, 1, 2, 3, etc.) como um argumento. Se você for seguir em frente
e criar uma ferramenta a partir desse script, como faremos na próxima parte desta lição,
é importante definir os parâmetros na mesma ordem em que você deseja que eles
apareçam na caixa de diálogo da ferramenta.
• Quando chamamos a ferramenta Buffer nesse script, fornecemos apenas três
parâmetros. Por não fornecer mais, aceitamos os valores padrão para o restante dos
parâmetros da ferramenta.
• Os blocos de código try/except são uma maneira de evitar que o script falhe
se houver algum um erro. Seu script tenta executar todo o código no bloco try. Se o script
não puder continuar por algum motivo, ele pula e executa o código no bloco except.
Inserir blocos try/except como aqui é uma boa prática de código quando você acha que
tirou todos os erros do seu script, ou quando quer ter certeza de que seu código irá
executar uma certa quantidade de linhas, não importa o que aconteça.
Quando você está escrevendo e depurando seu script pelas primeiras vezes, é mais
útil deixar de lado os blocos try/except e deixar o código travar, porque as mensagens de
erro (vermelhas) informadas na Janela Interativa às vezes fornecem melhores dicas sobre
39
como diagnosticar o problema de seu código. Suponha que você coloque uma declaração
de impressão em seu bloco, except dizendo "Houve um erro. Por favor, tente novamente."
Para o usuário final do seu script, isso é melhor do que ver uma mensagem de erro
desagradável (vermelha); no entanto, como um programador depurando o script, você
deseja ver a mensagem de erro (vermelha) para obter informações sobre o que deu errado.
• Os métodos arcpy.AddMessage() e arcpy.AddError() são formas de adicionar
mensagens adicionais ao usuário da ferramenta. Sempre que você executa uma
ferramenta, o geoprocessador imprime mensagens, as quais você provavelmente já viu
antes (por exemplo, “Executed (Buffer) successfully. End time: Sat Jun 22 07:37:31
2019”). Você tem o poder de adicionar mais mensagens por meio desses métodos.
Quando você usa arcpy.GetMessages(), você obtém todas as mensagens geradas
pela própria ferramenta. Estes lhe dirão coisas como se o usuário inseriu parâmetros
inválidos. Observe neste script a sintaxe um pouco complexa que você precisa usar para
primeiro obter as mensagens e, em seguida, adicione-as:
arcpy.AddMessage(arcpy.GetMessages()) . Se essa linha de código for confusa para
entender, lembre-se de que a ordem das funções funciona como operações matemáticas:
você começa trabalhando dentro dos parênteses primeiro para obter as mensagens e depois
as adiciona.
Os métodos AddError e addMessage são utilizados apenas quando fazemos
ferramentas de script para rodar no ArcMap. Quando você está apenas executando um script
no PythonWin (não fazendo uma ferramenta de script), você ainda pode obter as mensagens
usando uma instrução print com GetMessages(), assim: print arcpy.GetMessages().
Leituras
Leia as seções do Capítulo 5 que fala sobre como trabalhar com mensagens de
ferramenta (5.10) para outra perspectiva sobre como lidar com a saída da ferramenta.
40
• Abra o ArcMap e exiba a janela Catalog.
• Expanda os nós Toolboxes> My Tollboxes.
• Clique com o botão direito em My Toolboxes e clique em New> Toolbox.
• Dê um nome à sua caixa de ferramentas, como "MyScriptTools".
• Clique com o botão direito na sua nova caixa de ferramentas e clique em Add>
Script.
• Preencha as propriedades Name, Label e Description para sua ferramenta
Script, conforme mostrado abaixo:
41
de script. Em vez de aceitar qualquer string como entrada (que pode conter um erro), sua
ferramenta agora aplicará o requisito de que uma classe de feições seja usada como
entrada. O ArcGIS irá ajudá-lo, confirmando que o valor inserido é um caminho para uma
classe de feições válida. Ele até fornecerá aos usuários da sua ferramenta um botão de
navegação para que eles possam navegar até a classe de recursos.
Adicionando parâmetros
• Assim como você fez na etapa anterior, adicione um segundo parâmetro
denominado “Classe de feições de saída”. O tipo de dados deve ser novamente Feature
Class.
• Com o parâmetro de Classe de feições de saída ainda realçado, olhe para
baixo na parte Parameter Properties da caixa de diálogo. Altere a propriedade de
direção (Direction) para saída (Output).
42
• Com o parâmetro Distância do Buffer ainda destacado, olhe novamente para
a seção Parameter Properties. Defina a propriedade Default como "5 Kilometers" (não
inclua as aspas). Sua caixa de diálogo deve se parecer com o que você vê abaixo:
43
Resultado após a execução
• Este é um exemplo muito simples e, obviamente, você poderia simplesmente
executar a ferramenta Buffer out-of-the-box com resultados semelhantes. Normalmente,
quando você cria uma ferramenta de script, ela é apoiada por um script que executa uma
combinação de ferramentas e aplica alguma lógica que torna essas ferramentas
especialmente úteis.
• Há outro benefício para este exemplo. Observe a simplicidade da nossa caixa
de diálogo da ferramenta de script em comparação com a ferramenta principal Buffer:
44
Leituras
Leia Zandbergen 2.10 - 2.13 para reforçar o que você aprendeu durante esta lição
sobre scripts e ferramentas de script.
45
Mapeando os dados
É muito possível que você queira repetir o processo acima para testar diferentes
parâmetros de interpolação do IDW ou fazer mapas semelhantes com outros conjuntos de
dados (como os dados de precipitação de outros anos, por exemplo). Portanto, a série de
46
tarefas acima é bem adequada ao uso do ModelBuilder. Seu trabalho é criar um modelo que
possa completar a série de etapas acima sem precisar abrir manualmente quatro
ferramentas diferentes.
Parâmetros do modelo
Seu modelo deve ter estes (e somente estes) parâmetros:
• Dados de precipitação de entrada - Esta é a localização dos dados dos
pontos de leitura da precipitação. Esse é um parâmetro do modelo para que o modelo
possa ser facilmente executado novamente com outros conjuntos de dados.
• Power - Uma configuração do interppolador IDW que especifica a rapidez com
que a influência dos pontos ao redor diminui à medida que você se afasta do ponto a ser
interpolado.
• Raio de busca - Uma configuração do interpolador IDW que determina quantos
pontos ao redor estão incluídos na interpolação de um ponto. O raio de busca pode ser
fixado a uma certa distância, incluindo qualquer número de pontos que caiam dentro, ou
sua distância pode variar para que ele sempre inclua um número mínimo de pontos.
Quando você usa o ModelBuilder, não precisa configurar nenhuma dessas opções;
ModelBuilder faz isso para você quando você define o Raio de Pesquisa como um
parâmetro de modelo.
• Limites das zonas - Esta é uma tabela que permite ao usuário do modelo
especificar os limites das zonas para a classificação. Por exemplo, você poderia
configurar valores de precipitação de 1050 - 1295 para resultar em uma classificação de
1 (para corresponder à Zona 1), 1295 - 1480 poderia resultar em uma classificação de 2
(para corresponder à Zona 2) e assim por diante. A maneira de obter esta tabela é fazer
uma variável do parâmetro Reclassification da ferramenta Reclassify e defini-lo como
um parâmetro de modelo.
• Zonas de precipitação de saída - Esse é o local onde você deseja que o
conjunto de dados de saída de zonas de precipitação já recortado seja colocado no disco.
Ao construir seu modelo, você precisará definir algumas configurações que não serão
expostas como parâmetros. Estes incluem a feição de clipe, que é a região da bacia
hidrográfica, que corresponde ao arquivo Bacia_Hidrografica.shp na sua pasta de dados.
Há muitas outras configurações e parâmetros das ferramentas, como "Z Value field" e
"Input barrier polyline features" (para IDW) ou "Reclass field" (para Reclassify) que não
precisam ser expostos. Você deve definir esses valores apenas uma vez ao criar seu
modelo. Se você alguma vez pedir a alguém para executar este modelo, você não quer que
eles sejam carregados com escolhas diferentes; você deve apenas expor as coisas
essenciais que eles podem mudar.
Para esse modelo específico, você deve assumir que qualquer conjunto de dados de
entrada estará em conformidade com o mesmo esquema da classe de feições de
Plu_Total_Anual.shp. Por exemplo, um analista deve poder enviar um outro conjunto de
dados semelhante com os mesmos campos, nomes de campo e tipos de dados. No entanto,
manipular todos os tipos de esquemas de classe de feições tornaria seu modelo mais
complexo do que queremos para essa tarefa.
Quando você clica duas vezes no modelo para executá-lo, a interface deve se parecer
com o seguinte:
47
A interface do modelo
Executar o modelo com os parâmetros listados acima deve resultar no seguinte (eu
simbolizei as zonas no ArcMap com cores diferentes para ajudar a distingui-las). Esta é uma
maneira de verificar seu trabalho:
48
Dicas
As dicas a seguir podem ajudá-lo a construir seu modelo:
• Seu modelo precisa incluir as seguintes ferramentas nesta ordem: IDW (da
caixa de ferramentas do Spatial Analyst), Reclassify, Raster to Polygon, Clip (da caixa
de ferramentas Analysis).
• Uma maneira fácil de encontrar as ferramentas necessárias no ArcMap é clicar
em Windows > Search e digitar o nome da ferramenta desejada na caixa de pesquisa.
Tenha cuidado quando várias ferramentas tiverem o mesmo nome. Você normalmente
estará usando ferramentas da caixa de ferramentas do Spatial Analyst nesta tarefa.
• Depois de arrastar e soltar uma ferramenta na tela do ModelBuilder, clique duas
vezes nela e defina todos os parâmetros da maneira que desejar. Estas serão as
configurações padrão para o seu modelo.
• Se houver um determinado parâmetro para uma ferramenta que você deseja
expor como um parâmetro do modelo, clique com o botão direito do mouse na ferramenta
na tela ModelBuilder, em seguida, clique em Make variable > From parameter e escolha
o parâmetro. Quando o objeto oval aparecer para a variável, clique com o botão direito e
clique em Model Parameter.
• Se você receber erros que uma ferramenta não é capaz de executar ou que
não há nenhuma extensão do Spatial Analyst instalada, talvez seja necessário ativar a
extensão. No ArcMap, clique em Customize > Extensions e marque a caixa de seleção
Spatial Analyst.
49
• Consequentemente, você não é obrigado a criar uma ferramenta de script para
este exercício.
• Seu código deve ser executado corretamente no PythonWin. Para crédito total,
ele também deve conter comentários, tentar manipular erros e usar nomes de variáveis
intuitivas.
Entregas
As entregas para avaliação desta aula são:
• O arquivo .tbx da caixa de ferramentas que contém seu modelo de zonas de
precipitação. A maneira mais fácil de encontrá-lo é clicar com o botão direito do mouse
na caixa de ferramentas na janela Catalog, clicar em Propriedades e anotar o local. Se
você não puder navegar para esse caminho no Windows Explorer, precisará ativar a
opção Windows para mostrar arquivos e pastas ocultos.
• O arquivo .py contendo seu script para criar as curvas de nível.
• Um curto resumo (cerca de 400 palavras) descrevendo como você abordou os
dois problemas, quaisquer contratempos enfrentados e como lidou com eles.
50
Etapa 2: Fundamentos de Python e Programação
Objetivos da etapa 2
No final desta etapa, você deve:
• Entender a sintaxe básica do Python para instruções condicionais e controle
de fluxo de programa (if-else, operadores de comparação, for loop, while loop)
• Familiarize-se com tipos de dados mais avançados (strings, listas),
manipulação de strings e conversão entre diferentes tipos
• Sabar como depurar código e como usar o depurador
• Ser capaz de programar scripts básicos que usam instruções condicionais e
loops para automatizar tarefas
51
em determinada entrada do usuário. Se você souber como fazer cada uma dessas coisas
individualmente, poderá encaixar as peças, mesmo que a tarefa necessária pareça
assustadora.
Listas
Na etapa 1, você aprendeu sobre alguns tipos de dados comuns no Python, como
strings e inteiros. Às vezes, você precisa de um tipo que possa armazenar vários valores
relacionados juntos. O Python oferece várias maneiras de fazer isso, e a primeira sobre a
qual aprenderemos é a lista.
Aqui está um exemplo simples de uma lista. Você pode digitar isso na Janela Interativa
do PythonWin para acompanhar:
>>> Naipes = ['Espadas', 'Paus', 'Ouros', Copas]
Esta lista chamada 'Naipes' armazena quatro valores relacionados representando os
naipes em um baralho de cartas. Em muitas linguagens de programação, armazenar um
grupo de objetos em sequência como esse é feito com matrizes. Embora a lista do Python
possa ser considerada como uma matriz, ela é um pouco mais flexível do que a matriz típica
de outras linguagens de programação. Isso porque você pode colocar vários tipos de dados
em uma lista.
Por exemplo, suponha que quiséssemos criar uma lista para os valores das cartas que
você poderia desenhar. A lista pode ser assim:
>>> valores = ['Ás', 2, 3, 4, 5, 6, 7, 8, 9, 10, 'Valete', 'Dama', 'Rei']
Observe que você acabou de misturar valores de strings e inteiros na lista. Python. No
entanto, cada item na lista ainda tem um índice, significando um inteiro que indica o lugar de
cada item na lista. A lista começa com o índice 0 e, para cada item da lista, o índice é
incrementado em um. Tente isto:
>>> print (Naipes[0])
Espadas
>>> print (valores[12])
Rei
Nas linhas acima, você apenas solicitou o item com o índice 0 na lista de Naipes e
obteve 'Espadas'. Da mesma forma, você solicitou o item com índice 12 na lista de valores
e obteve 'King'.
Pode levar algum tempo inicialmente para lembrar que suas listas começam com um
índice 0. Testar seus scripts pode ajudar a evitar erros "off-by-one" que podem resultar do
esquecimento de que as listas são indexadas com zero. Por exemplo, você pode configurar
um script para crias 100 cartas aleatórias e imprimir os valores. Se nenhuma delas é um Ás,
você provavelmente criou o baralho fazendo os índices começarem em 1.
Lembre-se que você aprendeu que tudo é um objeto em Python. Isso também se aplica
às listas. Na verdade, as listas têm muitos métodos úteis que você pode usar para alterar a
ordem dos itens, inserir itens, classificar a lista e assim por diante. Tente isto:
52
>>> Naipes = ['Espadas', 'Paus', 'Ouros', 'Copas']
>>> Naipes.sort ()
>>> print (Naipes)
['Copas', 'Espadas', 'Ouros', 'Paus']
Observe que os itens na lista estão agora em ordem alfabética. Você também deve ter
notado que, quando você digitou "Naipes", recebeu ajuda para ver quais métodos estavam
disponíveis para a lista. Isso é chamado de autocompletar, e pode ser uma grande ajuda
quando você está escrevendo um código. Você quer verificar o que você pode fazer e não
pode fazer. Também pode ser uma maneira de evitar erros de digitação, pois você pode
descer a seta e pressionar Tab para inserir o método desejado. O autocompletar é um
recurso do PythonWin, mas esse tipo de ajuda pode ser encontrado em outros ambientes
de desenvolvimento integrados (IDEs), como o Microsoft Visual Studio.
O método sort() que você usou acima permitiu que você fizesse algo em uma linha de
código que, de outra forma, teria usado muitas linhas. Outro método útil como esse é o
reverse(), que permite classificar uma lista em ordem alfabética inversa:
>>> Naipes.reverse ()
>>> print (Naipes)
['Paus', ' Ouros ', 'Espadas', 'Copas']
Antes de tentar escrever um código de manipulação de listas, verifique a documentação
de referência da lista do Python para ver se existe um método existente que possa simplificar
seu trabalho.
Inserindo itens e combinando listas
O que acontece quando você quer combinar duas listas? Digite isto na janela interativa:
>>> lista1 = [101,102,103]
>>> lista2 = [104,105,106]
>>> lista3 = lista1 + lista2
>>> print (lista3)
[101, 102, 103, 104, 105, 106]
Observe que você não conseguiu [205,207,209]; em vez disso, o Python trata a adição
como acrescentando lista2 a lista1 . Em seguida, tente estas outras maneiras de adicionar
itens à lista:
>>> lista3 + = [107]
>>> print (lista3)
[101, 102, 103, 104, 105, 106, 107]
>>> lista3.append (108)
>>> print (lista3)
[101, 102, 103, 104, 105, 106, 107, 108]
53
Para colocar um item no final da lista, você pode adicionar uma lista de um item (como
adicionamos 107 à lista) ou usar o método append() na lista (como adicionamos 108 à lista).
Observe que lista3 + = [107] é uma forma abreviada de dizer lista3 = lista3 + [107].
Se você precisar inserir alguns itens no meio da lista, você pode usar o método insert():
>>> lista3.insert (4, 999)
>>> print (lista3)
[101, 102, 103, 104, 999, 105, 106, 107, 108]
Observe que o método insert() acima usou dois parâmetros. Você pode até ter notado
uma dica de ferramenta que mostra o que os parâmetros significam.
O primeiro parâmetro é a posição do índice que o novo item terá. Essa chamada de
método insere 999 entre 104 e 105. Agora, 999 está no índice 4.
Obtendo o tamanho de uma lista
Às vezes, você precisará descobrir quantos itens estão em uma lista, principalmente
quando estiver em um loop. Veja como você pode obter o tamanho de uma lista:
>>> minhaLista = [4,9,12,3,56,133,27,3]
>>> print (len(minhaLista))
8
Observe que len() fornece o número exato de itens na lista. Para obter o índice do item
final, você precisaria usar len(minhaLista) - 1. Novamente, essa distinção pode levar a erros
"off-by-one" se você não for cuidadoso.
Outras maneiras de armazenar coleções de dados
As listas não são a única maneira de armazenar coleções ordenadas de itens em
Python; você também pode usar tuplas e dicionários. As tuplas são como listas, mas você
não pode alterar os objetos dentro de uma tupla ao longo do tempo. Em alguns casos, uma
tupla pode, na verdade, ser uma estrutura melhor para armazenar valores como os naipes
em um baralho de cartas, porque essa é uma lista fixa que você não deseja que seu
programa mude acidentalmente.
Os dicionários diferem das listas uma vez que que os itens não são indexados; em vez
disso, cada item é armazenado com um valor de chave que pode ser usado para recuperar
o item. Usaremos os dicionários mais adiante no curso e sua tarefa de leitura desta lição
abordará o básico sobre dicionário de dados. A melhor maneira de entender como os
dicionários funcionam é brincar com alguns dos exemplos didáticos do livro na Janela
Interativa (ver Zandbergen 6.8).
Loops
Um loop é uma seção de código que repete uma ação. Lembre-se, o poder do script (e
computação em geral) é a capacidade de repetir rapidamente uma tarefa que pode ser
demorada ou propensa a erros para um ser humano. Looping é como você repete tarefas
54
com código; se está lendo um arquivo, procurando um valor ou executando a mesma ação
em cada item de uma lista.
Loop FOR
Um loop for faz algo com cada item em uma lista. Digite isso na Janela Interativa do
PythonWin para ver como funciona um loop simples:
>>> for nome in ["Lula", "Itamar", "Collor"]:
print (nome + "era um presidente do Brasil")
Depois de digitar isso, você terá que apertar Enter duas vezes seguidas para dizer ao
PythonWin que acabou de trabalhar no loop e que o loop deve ser executado. Você deveria
ver:
Lula era um presidente do Brasil
Itamar era um presidente do Brasil
Collor era um presidente do Brasil
Observe algumas coisas importantes sobre o loop acima. Primeiro, você declarou uma
nova variável, "nome", para representar cada item da lista à medida que você iterava. Tudo
bem fazer isso; na verdade, espera-se que você faça isso no início do loop for.
A segunda coisa a notar é que, após a condição, ou a primeira linha do loop, você
digitou dois pontos (:) e, em seguida, iniciou o recuo das linhas subseqüentes. Algumas
linguagens de programação requerem que você digite algum tipo de linha ou caractere
especial no final do loop (por exemplo, "Next" no Visual Basic ou "}" em JavaScript), mas o
Python procura apenas o local em que você usou um recuo. Ao pressionar Enter duas vezes,
você disse ao Python para parar o recuo e que estava pronto para executar o loop.
For Loops também pode trabalhar com listas de números. Experimente este na janela
interativa:
>>> x = 2
>>> multiplicadores = [1,2,3,4]
>>> for num in multiplicadores:
print (x * num)
2
4
6
8
No loop acima, você multiplicou cada item na lista por 2. Observe que você pode
configurar sua lista antes de começar a codificar o loop.
Você também poderia ter feito o seguinte com o mesmo resultado:
>>> multiplicadores = [1,2,3,4]
>>> for num in multiplicadores:
x = 2
55
print (x * num)
O código acima, no entanto, é menos eficiente do que o que fizemos inicialmente. Você
pode ver por quê? Desta vez você está declarando e configurando a variável x = 2 dentro do
loop. O interpretador Python agora terá que ler e executar essa linha de código quatro vezes
em vez de uma. Você pode pensar que essa é uma quantidade trivial de trabalho, mas se
sua lista continha milhares ou milhões de itens, a diferença no tempo de execução se tornaria
perceptível. Declarar e definir variáveis fora de um loop, sempre que possível, é uma prática
recomendada na programação.
Enquanto estamos no assunto, o que você faria se quisesse multiplicar 2 por cada
número de 1 a 1000? Definitivamente seria muita digitação para configurar manualmente
uma lista de multiplicadores como no exemplo anterior. Nesse caso, você pode usar a função
de intervalo interna do Python (Range). Tente isto:
>>> x = 2
>>> for num in range(1,1001):
print (x * num)
A função range é sua maneira de dizer ao Python: "Comece aqui e pare aí". Usamos
1001 porque o loop para um item antes do segundo argumento da função (os argumentos
são os valores que você coloca entre parênteses para dizer à função como executar). Se
você precisar da função para multiplicar por 0 no começo também, você pode até usar um
só argumento:
>>> x = 2
>>> for num in range(1001):
print (x * num)
A função range tem muitos usos interessantes que são detalhados em Zandbergen.
Loops WHILE
Um loop while é executado até que alguma condição seja atendida. Veja como codificar
nosso exemplo acima usando um loop while:
>>> x = 0
>>> while x <1001:
... print (x * 2)
... x + = 1
Loops while geralmente envolvem o uso de algum contador que monitora quantas
vezes o loop foi executado. Às vezes, você executará operações com o contador. Por
exemplo, no loop acima, x era o contador, e também multiplicamos o contador por 2 cada
vez durante o loop. Para incrementar o contador, usamos x + = 1, que é a abreviação de x
= x + 1, ou "add one to x".
Loops encadeados
Algumas situações exigem colocar um loop dentro de outro, uma prática chamada
nesting. Loops aninhados podem ajudá-lo a imprimir cada carta em um baralho (menos os
coringas):
>>> Naipes = ['Espadas', 'Paus', 'Ouros', 'Copas']
56
>>> valores = ['Ás', 2, 3, 4, 5, 6, 7, 8, 9, 10, 'Valete', 'Dama', 'Rei']
>>> for naipe in Naipes:
for valor em valores:
print (str(valor) + "de" + str(naipe))
No exemplo acima, você começa com um naipe e, em seguida, percorre cada valor da
ação, imprimindo o nome da carta. Quando você atinge o final da lista de valores, você pula
para fora do loop aninhado e volta para o primeiro loop para obter o próximo naipe. Então
você percorre todos os valores no segundo naipe e imprime os nomes das cartas. Este
processo continua até que todas as ações e valores tenham sido passados.
Looping em modelos SIG
Você usará loop repetidamente ao escrever scripts SIG em Python. Muitas vezes, você
precisará fazer uma iteração em todas as linhas de uma tabela, em todos os campos de uma
tabela ou em todas as classes de feições de uma pasta ou geodatabase. Você pode até
precisar percorrer os vértices de uma feição geográfica.
Você viu acima que os loops funcionam particularmente bem com listas. O arcpy possui
alguns métodos que podem ajudá-lo a criar listas. Aqui está um exemplo que você pode
tentar que usa arcpy.ListFeatureClasses() . Primeiro, crie manualmente uma nova pasta
C:\SEA5923\Dados2 . Em seguida, copie o código abaixo em um novo script no PythonWin
e execute o script. O script copia todos os dados da pasta Dados para a nova pasta que
você acabou de criar.
try:
arcpy.env.workspace = "C:/SEA5923/Dados"
except:
print ("O script falhou")
print (arcpy.GetMessages(2))
57
Observe acima que, uma vez que você tenha uma lista de classes de feições do Python
(fcList), é muito fácil configurar a condição de loop (for featureClass in fcList :).
Outra operação comum em scripts SIG é fazer um loop através de tabelas. Na verdade,
o módulo arcpy contém alguns objetos especiais chamados cursores que ajudam você a
fazer isso. Aqui está um pequeno script mostrando como um cursor pode percorrer cada
linha em uma classe de feições e imprimir o nome. Nós abordaremos os cursores em
detalhes adiante, então não se preocupe se algum código parecer confuso agora. O
importante é notar como um loop é usado para percorrer cada registro:
import arcpy
tabelaEntrada = "C:/SEA5923/Dados/Municipios.shp"
campo = "NOME"
linhas = arcpy.SearchCursor(tabelaEntrada)
58
...
Maior do que dois
No exemplo acima, a palavra-chave "if" indica que algum teste condicional está prestes
a ser executado. Nesse caso, a condição de x sendo maior que dois foi atendida, portanto,
o script imprimiu "Maior que dois". Observe que você é obrigado a colocar dois pontos (:)
após a condição e recuar qualquer código a ser executado por causa da condição. Para
consistência nesta classe, todo recuo é feito usando quatro espaços.
Usar "else" é uma maneira de executar o código se a condição não for atendida. Tente
isto:
>>> x = 1
>>> if x > 2:
... print ("Maior que dois")
... else:
... print ("Menor ou igual a dois")
...
Menor ou igual a dois
Observe que você não precisa colocar nenhuma condição depois de "else". É uma
maneira de pegar todos os outros casos. Novamente, o código condicional é recuado em
quatro espaços, o que torna o código muito fácil de ser entendido. O recuo é necessário
porque o Python não requer nenhum tipo de instrução "end if" (como muitas outras
linguagens) para indicar o final do código que você deseja executar.
Se você deseja executar várias condições, use "elif", que é a abreviação do Python
para "else if":
>>> x = 2
>>> if x > 2:
... print ("Maior que dois")
... elif x == 2:
... print ("Igual a dois")
... else:
... print ("Menor que dois")
...
Igual a dois
No código acima, elif x == 2: testa se x é igual a dois. O == é uma maneira de testar
se dois valores são iguais. Usar um único = nesse caso resultaria em um erro porque = é
usado para atribuir valores a variáveis. No código acima, você não está tentando atribuir a
“x” o valor de 2, você quer verificar se “x” é igual a 2, daí você usa ==.
Cuidado: Usar = em vez de == para verificar a equivalência é um erro muito comum no
Python, especialmente se você usou outras linguagens onde = é permitido para verificações
de equivalência.
59
Você também pode usar if, elif e else para lidar com várias possibilidades em um
conjunto. O código abaixo pega uma escola aleatória de uma lista (note que tivemos que
importar o módulo randon para fazer isso e chamar um método especial random.randrange()
). Depois que a escola é selecionada e seu nome é impresso, uma série de declarações if /
elif / else é exibida para lidar com cada possibilidade. Observe que a instrução else é deixada
como manipulador de erro; você não deve se deparar com essa linha se seu código funcionar
corretamente, mas você pode deixar a linha lá para se algo der errado.
import random
Manipulação de strings
Você já aprendeu como a variável de string (cadeias de caracteres) pode conter
números e letras e representar quase tudo. Ao usar o Python com o ArcGIS, sequências de
caracteres podem ser úteis para armazenar caminhos para dados e imprimir mensagens
para o usuário. Existem também alguns parâmetros da ferramenta de geoprocessamento
que você precisará fornecer como strings.
60
O Python possui algumas habilidades de manipulação de strings muito úteis. Não
entraremos em todos eles neste curso, mas seguiremos algumas técnicas que você precisa
conhecer.
Concatenando strings
Para concatenar duas strings, que significa anexar ou adicionar uma string ao final de
outra string. Por exemplo, você poderia concatenar as strings "Python is" e "uma linguagem
de script" para fazer a frase completa "Python é uma linguagem de script". Como você está
adicionando uma string a outra, é intuitivo que em Python você possa usar o sinal + para
concatenar strings.
Talvez seja necessário concatenar strings ao trabalhar com os nomes de caminho dos
arquivos. Às vezes é útil ou necessário armazenar uma string representando um diretório ou
geodatabase a partir da qual você está obtendo conjuntos de dados e uma segunda string
representando o próprio nome do conjunto de dados. Você coloca os dois juntos para ter o
caminho completo.
O exemplo a seguir, modificado da Ajuda do ArcGIS, demonstra esse conceito.
Suponha que você já tenha uma lista de strings representando as classes de feições que
você deseja recortar. A lista é representada por "featureClassList" neste script:
pastaEntrada = "c:\\SEA5923\\Dados\\FC\\"
pastaResultados = "c:\\SEA5923\\FC\\resultados\\"
clipFeature = "c:\\SEA5923\\Dados\\Consorcio_mun.shp"
61
fosse "Hintegrada.shp", a cadeia de saída resultante seria
"C:\\SEA5923\\Dados\\FC\\resultados\\Hintegrada.shp"
O exemplo acima mostra que a concatenação de strings pode ser útil em looping.
Construir o caminho de saída usando um espaço de trabalho (workspace) do conjunto de
dados ou o nome de pasta seguido por um nome da classe de feições de uma lista fornece
muito mais flexibilidade do que tentar criar cadeias de caminho de saída para cada conjunto
de dados individualmente. Você pode não saber quantas classes de recursos estão na lista
ou quais são seus nomes. Você pode contornar isso se construir os caminhos de saída
através da concatenação de strings.
Casting para uma string
Às vezes, em programação, você tem uma variável de um tipo que precisa ser tratada
como outro tipo. Por exemplo, 5 pode ser representado como um número ou uma string. O
Python só pode executar cálculos matemáticos com o valor 5 se este for tratado como um
número e só pode concatenar o valor 5 em uma string existente se for tratada como uma
string.
O Casting é uma forma de forçar seu programa a pensar em uma variável como um
tipo diferente. Crie um novo script no PythonWin e digite ou cole o seguinte código:
x = 0
while x < 10:
print (x)
x += 1
print ("Você executou o loop " + x + " vezes.")
Agora tente executá-lo. O script tenta concatenar cadeias com a variável x para imprimir
quantas vezes você executou um loop, mas resulta em um erro: "TypeError: pois não é
possível concatenar objetos 'str' e 'int'." O Python não tem problema quando você deseja
imprimir a variável x por conta própria, mas o Python não pode misturar strings e variáveis
inteiras em uma instrução de impressão. Para rodar o código, você tem que converter a
variável x em uma sequência de caracteres quando você tenta imprimi-lo.
x = 0
while x < 10:
print (x)
x += 1
print ("Você executou o loop " + str(x) + " vezes.")
Você pode forçar o Python a pensar em x como uma string usando str(x). O Python tem
outras funções de conversão, como int() e float(), que você pode usar se precisar ir de uma
string para um número. Use int() para inteiros e float() para decimais.
Leituras
É hora de fazer uma pausa e fazer algumas leituras de outra fonte. Se você é novo
com script Python, isso ajudará você a ver os conceitos de um outro ângulo.
Leia os capítulos 4 - 6 de Zandbergen (pule as partes do Capítulo 5 que você já leu na
etapa 1).
62
• O Capítulo 4 aborda os fundamentos da sintaxe Python, loops, strings e outras
coisas que acabamos de aprender.
• O capítulo 5 fala sobre geoprocessamento com arcpy. Leia as seções que
pulamos na etapa 1 - 5.7, 5.8
• O Capítulo 6 fornece algumas instruções específicas sobre como trabalhar com
os conjuntos de dados do ArcGIS.
63
• Cachorro visita seu balde de cerejas (Adicione 2 cerejas)
• Balde derramado (Coloque as 10 cerejas de volta na sua árvore)
Os jogadores continuam se revezando até que algum tenha 0 cerejas na sua árvore, e
nesse ponto será o ganhador do jogo. Seu objetivo aqui é escrever um script que simula o
jogo (e por simplificação adotaremos que você está jogando sozinho), imprimindo o seguinte:
• O resultado de cada rodada
• O número de cerejas na sua árvore após cada jogada. Isso deve estar sempre
entre 0 e 10.
• O número final de jogadas necessárias para ganhar o jogo.
Aproximando-se de um problema de programação
Embora este exemplo possa parecer juvenil, é uma excelente maneira de praticar tudo
o que você acabou de aprender. Como iniciante, você pode parecer intimidado pelo
problema acima. Uma pergunta comum é: "Por onde começo?" A melhor abordagem é dividir
o problema em pedaços menores de coisas que você sabe fazer.
Uma das habilidades de programação mais importantes que você pode adquirir é a
capacidade de verbalizar um problema e traduzi-lo em uma série de pequenas etapas de
programação (construção do algoritmo). Aqui está uma lista de coisas que você precisa fazer
neste script. Os programadores chamam esse pseudocódigo porque ele não está escrito em
código, mas segue a sequência que o código precisará tomar.
• Gire a roleta
• Imprima o resultado da roleta
• Adicione ou remova cerejas com base no resultado
• Certifique-se de que o número de cerejas esteja entre 0 e 10
• Imprima o número de cerejas na árvore
• Vá para a próxima rodada ou imprima o número de jogadas que levou para
ganhar o jogo
Também ajuda listar as variáveis que você precisará:
• Número de cerejas atualmente na árvore (começa em 10)
• Número de jogadas realizadas (começa em 0)
• Valor da roleta (Aleatório)
Vamos tentar abordar cada uma das etapas do pseudocódigo. Não se preocupe com
o fluxo total do script ainda. Em vez disso, tente entender como cada etapa do problema
deve ser resolvido com o código. Montar os blocos de código no final é relativamente trivial.
Gire a roleta
Como você simula um giro aleatório? Em um dos nossos exemplos anteriores, usamos
o módulo aleatório para gerar um número aleatório dentro de um intervalo de inteiros; no
entanto, as escolhas nesta roleta não são lineares. Uma boa abordagem aqui é armazenar
todas as possibilidades em uma lista e usar o gerador de números aleatórios para escolher
o índice para uma das possibilidades. Por si só, o código ficaria assim:
64
import random
valoresRoleta = [-1, -2, -3, -4, 2, 2, 10]
roletaIndex = random.randrange(0, 7)
resultadoRoleta = valoresRoleta[roletaIndex]
A lista valoresRoleta contém todos os resultados possíveis de uma rodada (remova 1
cereja, remova 2 cerejas, etc.). O valor final 10 representa o balde derramado (colocando
todas as cerejas de volta na árvore).
Você precisa escolher um valor aleatório fora desta lista para simular um giro. A variável
roletaIndex representa um inteiro aleatório de 0 a 6, que é o índice do item que você retirará
da lista. Por exemplo, se roletaIndex for 2, seu resultado da roleta é -3 (remova 3 cerejas da
árvore). O valor é atribuído a variável resultadoRoleta.
O método random.randrange() é usado para selecionar os números aleatórios. No
início do seu script, você precisa importar o módulo random para usar esse método.
Imprima o resultado da roleta
Depois de obter um resultado, basta uma linha de código para imprimi-lo. Você terá
que usar o método str() para convertê-lo em uma string.
print ("Você tirou" + str(resultadoRoleta) + ".")
Adicione ou remova cerejas com base no resultado
Como mencionado acima, você precisa ter alguma variável para acompanhar o número
de cerejas na sua árvore. Essa é uma daquelas variáveis que o nome precisa ser intuitivo:
cerejasNaArvore = 10
Depois de completar um “giro” da roleta, você precisa modificar essa variável com base
no resultado. Lembre-se de que o resultado é mantido na variável resultadoRoleta e que um
resultado negativo remove as cerejas da sua árvore. Então, seu código para modificar o
número de cerejas na árvore seria semelhante a:
cerejasNaArvore + = resultadoRoleta
Certifique-se de que o número de cerejas esteja entre 0 e 10
Se você ganhar o jogo você tem 0 cerejas. Você não precisa atingir exatamente 0, mas
não faz sentido dizer que você tem cerejas negativas. Da mesma forma, você pode tirar na
roleta o balde derramado, que por simplicidade representamos com 10 positivos em
valoresRoleta. Você não tem permissão para ter mais de 10 cerejas na árvore.
Uma simples estrutura de decisão if / elif pode ajudá-lo a manter o valor de
cerejasNaArvore entre 0 e 10:
if cerejasNaArvore > 10:
cerejasNaArvore = 10
elif cerejasNaArvore <0:
cerejasNaArvore = 0
Isso significa que, se você acabar com mais de 10 cerejas na árvore, defina
cerejasNaArvore de volta para 10. Se você acabar com menos de 0 cerejas, defina
cerejasNaArvore como 0.
65
Imprima o número de cerejas na árvore
Tudo o que você precisa fazer para essa etapa é imprimir sua variável
cerejasNaArvore, convertendo-a em uma string para que ela possa ser inserida em uma
frase.
print ("Você tem" + str (cerejasNaArvore) + "cerejas na sua árvore.")
Jogue outra vez ou imprima o número de jogadas que levou para ganhar o jogo
Você provavelmente previu que teria que descobrir uma maneira de fazer várias
jogadas. Este é o cenário perfeito para um loop.
Qual é a condição do loop? Tem que haver algumas cerejas na árvore para começar
outra jogada, então você pode começar o loop desta maneira:
while cerejasNaArvore > 0:
Muito do código que escrevemos acima entraria no loop para simular uma jogada.
Como precisamos acompanhar o número de jogadas realizadas, no final do loop, precisamos
incrementar um contador:
jogadas + = 1
Essa variável teria que ser inicializada no início do script, antes do loop.
Este código pode imprimir o número de jogadas ao final do jogo:
print ("Demorou" + str (jogadas) + " para ganhar o jogo.")
Código final
Sua única tarefa restante é reunir os códigos acima em um script. Abaixo está um
exemplo de como o script final ficaria. Copie isso em um novo script PythonWin e tente
executá-lo:
66
# Adicione ou remova cerejas com base no resultado
cerejasNaArvore += resultadoRoleta
# Número de cerejas deve estar entre 0 e 10
if cerejasNaArvore > 10:
cerejasNaArvore = 10
elif cerejasNaArvore < 0:
cerejasNaArvore = 0
# Print o número de cerejas na árvore
print ("Você tem " + str(cerejasNaArvore) + " cerejas.")
jogadas += 1
# Print o número de jogadas para vencer o jogo
print ("Você precisou de " + str(jogadas) + " para vencer.")
lastline = raw_input(">")
Análise do código final
Revise o código final de perto e considere as seguintes coisas.
A primeira coisa que você faz é importar os módulos de suporte necessários, neste
caso, o módulo random.
Em seguida, você declara as variáveis que você usará ao longo do script. Cada variável
tem um escopo, que determina o quanto ela é amplamente usada em todo o script. As
variáveis valoresRoleta, jogadas e cerejasNaArvore são necessárias no script inteiro,
portanto, elas são declaradas no início, fora do loop. As variáveis usadas em todo o seu
programa como esse têm escopo global. Por outro lado, as variáveis roletaIndex e
resultadoRoleta têm escopo local porque são usadas apenas dentro do loop. Cada vez que
o loop é executado, essas variáveis são reinicializadas e seus valores mudam.
Você poderia declarar a variável valoresRoleta dentro do loop e obter o mesmo
resultado final, mas o desempenho seria mais lento porque a variável teria que ser
reinicializada toda vez que você executasse o loop. Quando possível, você deve declarar
variáveis fora dos loops por esse motivo.
Se você tivesse declarado as variáveis jogadas ou cerejasNaArvore dentro do loop,
seu código teria erros lógicos. Você estaria essencialmente começando o jogo novamente
em cada jogada com 10 cerejas na sua árvore, tendo tomado 0 jogadas. Na verdade, você
criaria um loop infinito porque não há como remover 10 cerejas durante uma jogada, e a
condição de loop sempre seria avaliada como verdadeira. Novamente, tenha muito cuidado
com o local em que você declara suas variáveis quando o script contém loops.
Observe que o número total de jogadas é impresso fora do loop quando o jogo termina.
A linha final lastline = raw_input (">") lhe retorna um cursor vazio solicitando uma entrada
e é apenas um truque para garantir que o aplicativo não desapareça quando terminar (se
você executar o script a partir de um console de comando).
Resumo
67
No exemplo acima, você viu como listas, loops, estruturas de decisão e conversão de
variáveis podem trabalhar juntos para ajudá-lo a resolver um desafio de programação. Você
também aprendeu como abordar um problema de analisando uma tarefa de cada vez para
depois montá-las em um script.
Atividade de desafio
Se a atividade acima fez você se entusiasmar em escrever algum programa, pegue o
script acima e tente encontrar o número médio de jogadas necessárias para vencer um jogo
de Hi-Ho! Cherry-O. Para fazer isso, adicione outro loop que execute o jogo um grande
número de vezes, digamos 10000. Você precisará registrar o número total de turnos
necessários para vencer todos os jogos e dividir pelo número de jogos (use "/" para a
divisão). Você também poderia incluir outros jogadores e alternar as jogadas entre eles.
68
Problemas potenciais e diagnóstico rápido
O segredo da programação bem-sucedida é a experiência e não ter medo de errar
quando você executa o código pela primeira vez. Depurar, ou encontrar erros no código, faz
parte da vida dos programadores. Aqui estão algumas coisas que podem acontecer:
• Seu código não roda, geralmente por causa de um erro de sintaxe (você digitou
algum código ilegal do Python).
• Seu código é executado, mas o script não é concluído e relata um erro.
• Seu código é executado, mas o script nunca é concluído. Muitas vezes isso
ocorre quando você criou um loop infinito.
• Seu código é executado e o script é concluído, mas não fornece o resultado
esperado. Isso é chamado de erro lógico e geralmente é o tipo de erro que exige mais
esforço para depurar.
Não tenha medo de erros
Erros acontecem. Existem muito poucos programadores que podem se sentar e, acima
de tudo, escrever dezenas de linhas de código livre de bugs. Isso significa algumas coisas
para você:
• Espere gastar algum tempo lidando com erros durante o processo de
construção de scripts. Os programadores iniciantes às vezes subestimam quanto tempo
isso leva. Para obter uma estimativa inicial, você pode considerar o tempo necessário
para elaborar suas linhas de código, duplicá-lo ou triplicá-lo para acomodar o tratamento
de erros e o polimento final do script e da ferramenta.
• Não tenha medo de executar seu script e consertar os erros. Uma boa
estratégia é escrever uma pequena parte da funcionalidade, executá-la para garantir que
ela funcione e, em seguida, adicionar a próxima peça. Por uma questão de discussão,
vamos supor que, como um novo programador, você introduza um novo bug uma vez a
cada 10 linhas de código. É muito mais fácil encontrar um único bug em 10 novas linhas
de código do que encontrar 5 bugs em 50 novas linhas de código. Se você estiver
construindo seu script bloco por bloco e depurando com frequência, poderá fazer uma
avaliação mais rápida e precisa de onde introduziu novos erros.
Captura de erros de sintaxe
Erros de sintaxe ocorrem quando você digita algo incorretamente e seu código se
recusa a executar. Erros comuns de sintaxe incluem o esquecimento de dois pontos ao
definir um loop ou uma condição if, usando barras invertidas simples em um nome de
arquivo, fornecendo o número errado de argumentos a uma função ou tentando misturar
tipos de variáveis incorretamente, como dividir um número por uma string.
Quando você tenta executar código com um erro de sintaxe no PythonWin, talvez não
perceba nada acontecer. Na parte inferior da janela, procure uma mensagem como "Falha
ao executar script - erro de sintaxe - sintaxe inválida" ("Failed to run script - syntax error -
invalid syntax").
Às vezes a mensagem é mais clara. Por exemplo, se você recuar uma linha apenas
três espaços em vez de quatro, verá: "Falha ao executar script - erro de sintaxe - recuo
inesperado" ("Failed to run script - syntax error - unexpected indent").
69
Você pode verificar erros de sintaxe antes de executar seu código usando o botão
Check na barra de ferramentas Standard do PythonWin. Esse botão verifica se há erros
e os relata em uma pequena mensagem na parte inferior da janela, assim como você veria
se tentasse executar seu código com um erro de sintaxe. Se não houver erros, você verá
uma mensagem como "O Python e o TabNanny verificaram com êxito o arquivo
'myScript.py'" (O TabNanny é um módulo que o PythonWin usa para verificar a identação
correta).
Lidando com falhas
Se o seu código falhar, você poderá ver uma mensagem de erro na Janela Interativa
ou no console. Em vez de bater a cabeça contra a mesa, você deve se alegrar com o fato
de que o software possivelmente relatou a você exatamente o que deu errado! Vasculhe a
mensagem em busca de pistas sobre qual linha de código causou o erro e qual foi o
problema. Faça isso mesmo se a mensagem parecer intimidante. Por exemplo, veja se você
consegue entender o que causou essa mensagem de erro:
Traceback (most recent call last):
File "C:\Python27\Lib\site-
packages\pythonwin\pywin\framework\scriptutils.py", line 310, in
RunScript
exec codeObject in __main__.__dict__
File "C:\PSU_Python_Practice\syntax_error_practice.py", line 4, in
<module>
x = x / 0
ZeroDivisionError: integer division or modulo by zero
Embora a mensagem comece com algum conteúdo que você provavelmente não
entende, é possível verificar que o erro foi causado na Linha 4: x = x / 0. A divisão por 0 não
é possível e o computador não poderá fazê-lo.
É mais fácil interpretar mensagens como essa se você exibiu números de linha para o
seu código no PythonWin. Para obter os números de linha:
• No PythonWin, clique em View > Options.
• Clique na guia Editor.
• Defina a propriedade de números de linha (Line Numbers) para um número
maior, como 30.
Os números de linha também são úteis se você fizer um e-mail ou postar em algum
fórum sobre seu código e incluir o script. Você pode apontar imediatamente a linha erro para
seus colegas.
Depuração Ad-hoc
Às vezes é fácil incluir algumas instruções de 'print' em todo o código para descobrir
até onde ele executou ou para verificar o que está acontecendo com certos valores no script
enquanto ele é executado. Isso também pode ser útil para verificar se seus loops estão
fazendo o que você espera e se está evitando erros "off-by-one".
Suponha que você esteja tentando encontrar o valor médio (médio) dos itens em uma
lista com o código abaixo.
70
# Encontre a média dos itens numa lista
lista = [22,343,73,464,90]
for item in lista:
total = 0
total += item
media = total / len(lista)
print ("A média é " + str(media))
O script informa "A média é 18", o que não parece correto. A partir de uma rápida
verificação visual dessa lista, você poderia imaginar que a média seria maior que 100. O
script não está pegando erroneamente o número 18 da lista; não é um dos valores. Então,
de onde vem isso? Você pode colocar algumas instruções estratégicas de impressão no
script para obter um relatório melhor sobre o que está acontecendo:
# Encontre a média dos itens numa lista
lista = [22,343,73,464,90]
for item in lista:
print ("Processando o loop...")
total = 0
total += item
print (total)
print (len(lista))
media = total / len(lista)
print ("Executando a divisão...")
print ("A média é " + str(media))
Agora, quando você executa o script, você vê.
Processando o loop ...
22
Processando o loop ...
343
Processando o loop ...
73
Processando o loop ...
464
Processando o loop ...
90
5
Executando divisão ...
Média é 18
O erro agora se torna mais claro. O total em execução não está sendo mantido com
sucesso; em vez disso, ele é redefinido toda vez que o loop é executado. Isso faz com que
o último valor, 90, seja dividido por 5, gerando uma resposta de 18. Você precisa inicializar
71
a variável para o total fora do loop para evitar que isso aconteça. Depois de corrigir o código
e remover as instruções de impressão, você obtém:
# Encontre a média dos itens numa lista
lista = [22,343,73,464,90]
total = 0
for item in lista:
total += item
media = total / len(lista)
print ("A média é " + str(media))
O resultado "A média é 198" parece muito melhor. Você corrigiu um erro lógico no seu
código: um erro que não faz o seu script falhar, mas produz o resultado errado.
Embora a depuração com instruções de impressão seja rápida e fácil, você precisa ser
cuidadoso com ela. Depois de corrigir seu código, lembre-se de remover as instruções para
tornar seu código mais rápido e menos confuso. Além disso, adicionar instruções de
impressão se torna impraticável para scripts longos ou complexos. Você pode identificar os
problemas mais rapidamente e rastrear muitas variáveis ao mesmo tempo usando o
depurador do PythonWin, que é abordado na próxima seção.
72
print (numero)
Mesmo que você consiga identificar o erro, siga os passos abaixo para ter uma idéia
do processo de depuração e da barra de ferramentas Debugging do PythonWin.
• Abra o PythonWin e copie o código acima em um novo script.
• Salve seu script como fatorial.py. Você pode, opcionalmente, executar o
script, mas não obterá um resultado e poderá ter que fechar o PythonWin para voltar ao
local onde estava.
• Clique em View > Toolbar e verifique se a opção Debugging está marcada.
Muitos IDEs têm barras de ferramentas de depuração como essa, e as ferramentas que
elas contêm são bastante padronizadas: uma maneira de executar o código, uma
maneira de definir pontos de interrupção, uma maneira de percorrer o código linha por
linha e uma maneira de observar o valor das variáveis enquanto percorre-se o código.
Vamos analisar cada uma delas nas etapas abaixo.
• Defina o seu cursor na linha (numero = 5) e clique no botão Toggle Breakpoint
. Um ponto de interrupção é um local onde você deseja que seu código pare de ser
executado para que você possa examiná-lo linha por linha usando o depurador. Muitas
vezes, você definirá um ponto de interrupção no meio do script para não precisar
examinar cada linha de código. Neste exemplo, o script é muito curto, então estamos
colocando o ponto de interrupção no começo. O ponto de interrupção é representado por
um círculo ao lado da linha de código e isso é comum em outros depuradores também.
• Clique no botão Step . Isso executa uma linha do seu código. Observe na
sua janela de observação que a variável "numero" agora tem um valor de 5.
• Clique no botão Step novamente. Desta vez, a variável "multiplicador" foi
atribuída a um valor.
• Clique no botão Step mais algumas vezes para percorrer o loop. Vá devagar e
use a janela de observação para entender o efeito que cada linha tem nas duas variáveis.
73
• Percorra o loop até que "multiplicador" atinja um valor de 10. Deve ficar óbvio,
neste ponto, que o loop não saiu no ponto desejado. Nossa intenção era que ele
desistisse quando "numero" chegasse a 120.
• Você consegue identificar o erro agora? O fato de o loop não ter saído deve
chamar sua atenção para a condição de loop. O loop só sairá quando "multiplicador" for
maior que ou igual a "numero". Obviamente, isso nunca acontecerá, já que "numero"
continua ficando maior e maior à medida que é multiplicado a cada vez por meio do loop.
Neste exemplo, o código continha um erro lógico. Ele reutilizou a variável para a qual
desejamos encontrar o fatorial (5) como uma variável na condição de loop, sem considerar
que o número seria repetidamente aumentado dentro do loop. Alterar a condição de loop
para o seguinte faria com que o script funcionasse:
while multiplicador <5:
Melhor ainda do que codificar o valor 5 nessa linha seria inicializar uma variável inicial
e configurá-la como igual ao número cujo fatorial queremos localizar. O número pode então
ser multiplicado independentemente da variável de condição de loop.
• Feche o PythonWin e abra novamente para um novo script. Cole o código
abaixo e salve o script como fatorial2.py.
# Este script calcula o fatorial de um número
# inteiro, que é o produto desse inteiro e de
# todos os inteiros positivos menores que ele
number = 5
loopStop = numero
multiplicador = 1
while multiplicador < loopStop:
numero *= multiplicador
multiplicador += 1
print (numero)
• Exiba a barra de ferramentas Debugging e percorra o loop algumas vezes,
como fez anteriormente. Observe os valores das variáveis "numero" e "multiplicador",
mas, desta vez, adicione também a variável "loopStop". Essa variável permite que a
condição de loop permaneça constante enquanto "numero" é multiplicado. Na verdade,
você deve ver "loopStop" permanecer fixo em 5, enquanto "numero" aumenta para 120.
• Continue avançando até que "numero" atinja 120 e você atinja a linha
"print(numero)". Nesta linha, não pressione o botão Step; em vez disso, basta pressionar
Go para finalizar o script. (Você não quer percorrer todo o código Python interno
necessário para imprimir a variável.) Nesse ponto, o valor de "numero" deve ser 120, que
é 5 fatorial. Se você quiser, você pode tentar substituir outros inteiros como o valor de
"numero" para encontrar seus fatoriais.
No exemplo acima, você usou a barra de ferramentas Depuração para localizar um erro
lógico que causou um loop infinito em seu código. As ferramentas de depuração geralmente
são seu melhor recurso para localizar erros sutis em seu código.
Se você acessar uma função interna do Python, como “print”, enquanto estiver usando
o Debug, o depurador irá adentrar diretamente em todo o código Python necessário para
executar a função. Você saberá quando isso acontecer, porque você verá uma ou mais
janelas abertas com códigos difíceis de entender. Este também é o caso, por vezes, quando
você executa funções arcpy. O problema é agravado porque esse tipo de código tende a
chamar outras funções, o que acaba abrindo muitas janelas.
74
Se você não quiser ver todo esse código, pode tentar o atalho usando o botão Steo
Over para pular uma função complexa ou Step Out para sair da função. Se
percorrer todo esse código é muito confuso, você pode definir outro ponto de interrupção
uma ou duas linhas além da linha com a função e apenas pressionar o botão Go novamente
para executar até o próximo ponto de interrupção. Quando você pressiona o botão Go, o
depurador não pára até atingir o próximo ponto de interrupção.
Você pode e deve praticar usando a barra de ferramentas de depuração nas tarefas
que você recebe neste curso. Você pode economizar muito tempo dessa forma.
Leituras
Leia Zandbergen 11.1 - 11.5 para obter dicas para depuração. Em seguida, leia 11.11
e consulte na seção sobre depuração uma lista de verificação para revisar toda vez que você
encontrar um problema em seu código.
75
arcpy.GetMessages(2) retornaria apenas as mensagens com uma gravidade de "Erro".
Mensagens de erro e aviso às vezes incluem um código exclusivo que você pode usar para
procurar mais informações sobre a mensagem. A Ajuda do ArcGIS Desktop contém tópicos
que listam os códigos de mensagem e fornecem detalhes sobre cada um deles. Algumas
das entradas têm dicas para corrigir o problema.
Try / except pode ser usado de várias maneiras e em diferentes níveis de identação
em um script. Por exemplo, você pode ter um único try / except como no exemplo acima,
onde o try-block contém toda a funcionalidade do seu programa. Se algo der errado, o script
exibirá uma mensagem de erro e será encerrado. Em outras situações, convém dividir o
código principal em partes diferentes, cada uma contida por sua própria try / except para
lidar com os problemas específicos que podem ocorrer nessa parte do código. Por exemplo,
a seguinte estrutura pode ser usada em um script em lote que realiza duas operações de
geoprocessamento diferentes em um conjunto de shapefiles quando uma tentativa deve ser
feita para executar a segunda operação, mesmo se a primeira falhar.
for featureClass in fcList:
try:
. . . # realizar operação de geoprocessamento 1
except:
. . . # lidar com falha de operação de geoprocessamento 1
try:
. . . # realizar operação de geoprocessamento 2
except:
. . . # lidar com falha de operação de geoprocessamento 2
Vamos supor que a primeira operação de geoprocessamento falhe para o primeiro
shapefile em fcList. Como resultado, a execução do programa irá para o primeiro bloco
except que contém o código para lidar com esta situação de erro. No caso mais simples,
apenas produzirá algumas mensagens de saída. Depois que o bloco-except foi executado,
a execução do programa continuará normal ao passar para a segunda instrução try / except
e tentar executar a segunda operação de geoprocessamento. Ou este é bem-sucedido ou
falha também, caso em que o segundo bloco except será executado. A última coisa a notar
é que, já que ambas as instruções try / except estão contidas no corpo do loop for, a instrução
segue pelos diferentes shapefiles da lista, mesmo que ambas as operações falhem em um
dos arquivos.
Leitura adicional
Dê uma olhada na documentação oficial do ArcGIS para mais detalhes sobre
mensagens de geoprocessamento. Não deixe de ler estes tópicos:
Entendendo os tipos e a gravidade das mensagens
(http://desktop.arcgis.com/en/arcmap/latest/analyze/python/message-types-and-
severity.htm)
Entendendo os erros e avisos da ferramenta de geoprocessamento
(https://pro.arcgis.com/en/pro-app/tool-reference/appendices/understanding-
geoprocessing-tool-errors-and-warnings.htm)
Este é o gateway na seção de referência de erro e aviso da ajuda que explica todos os
códigos de erro. Às vezes, você verá esses códigos nas mensagens recebidas e o tópico de
ajuda específico do código pode ajudá-lo a entender o que deu errado. O artigo também fala
76
sobre como você pode capturar determinadas condições em seus próprios scripts e fazer
com que códigos de erro específicos apareçam.
77
um bom lugar para aprender sobre os módulos do Python, como "os", "csv", "math" ou
"random".
Livros impressos
O livro texto Python Scripting for ArcGIS é uma introdução bem escrita para o que o
título diz: trabalhar com o ArcGIS usando Python. Existem alguns outros livros que
começaram a aparecer sobre este assunto e eu antecipo que haverá mais.
Uma boa referência geral do Python é o Learning Python, de Mark Lutz. Ele cobre
tópicos iniciantes e avançados, então não se preocupe se algumas partes dele parecerem
intimidadoras.
Fóruns ESRI e outros fóruns online
Os fóruns Esri são um lugar onde você pode fazer perguntas para outros usuários de
software ESRI, ou ler sobre problemas encontrados por outros usuários que podem ser
semelhantes aos seus. Existe um fórum do ESRI sobre Python relacionado a scripts com o
ArcGIS, e também um fórum mais geral de Geoprocessamento que você pode achar útil.
https://community.esri.com/community/developers/gis-developers/python
https://community.esri.com/community/gis/analysis/geoprocessing
Antes de postar uma pergunta nos fóruns da ESRI, faça uma pequena pesquisa para
se certificar de que a pergunta ainda não foi respondida, pelo menos recentemente.
Existem muitos outros fóruns on-line que abordam questões de programação ou SIG.
Você os verá por toda a Internet se fizer uma pesquisa no Google sobre como fazer algo no
Python. O Stack Exchange é um exemplo de um fórum técnico bem explorado, leve em
anúncios, que permite aos leitores promover ou rebaixar respostas, dependendo de sua
utilidade. Um de seus sites filho, o GIS Stack Exchange, trata especificamente de problemas
de SIG e cartografia.
http://gis.stackexchange.com/
Se você postar em fóruns on-line, forneça informações detalhadas sobre o problema e
liste o que já experimentou. Declare o problema em um sentido geral e foque no código do
problema.
78
Exercício 1: Encontrar os espaços em uma lista de nomes
Os objetos String do Python têm um método de índice que permite encontrar uma
substring na string maior. Por exemplo, se eu tivesse uma variável definida como nome =
"Joe Paterno" e se guisse com a expressão nome.index ("Pa") , ela retornaria o valor 4
porque a substring "Pa" começa no caractere 4 no string mantida em nome. (O primeiro
caractere em uma string está na posição 0.)
Para este exercício prático, comece criando uma lista de nomes como o seguinte:
beatles = ["John Lennon", "Paul McCartney", "Ringo Starr", "George
Harrison"]
Em seguida, escreva um código que percorrerá todos os itens da lista, imprimindo uma
mensagem como a seguinte:
"Há um espaço no nome de ________ na posição ____." onde o primeiro espaço em
branco é preenchido com o nome atualmente sendo processado pelo loop e o segundo
espaço em branco é preenchido com a posição do primeiro espaço no nome conforme
retornado pelo método de índice. (Você deve obter valores de 4, 4, 5 e 6, respectivamente,
para os itens da lista acima.)
Você pode começar configurando um loop e simplesmente imprimindo cada nome. Se
você fizer isso funcionar, veja se consegue simplesmente imprimir as posições do espaço.
Depois de conseguir isso, tente colocar o nome e as posições de espaço na mensagem
maior.
79
A:90-100
B:80-89
C:70-79
D:60-69
F:<60
80
Projeto 2: Ferramenta para reprojetar conjuntos de dados
vetoriais em lote (batch)
Alguns órgãos que trabalham com SIG determinaram um único sistema de referência
padrão para seus dados de origem. Os conjuntos de dados brutos, no entanto, podem ser
obtidos de terceiros em outros sistemas de referência. Esses conjuntos de dados precisam
então ser reprojetados para a projeção padrão. Reprojetar arquivos em lote, ou reprojetar
muitos conjuntos de dados de uma só vez, é uma tarefa adequada para a criação de scripts.
Neste projeto você irá praticar os fundamentos do Python escrevendo um script que
reprojetará os conjuntos de dados vetoriais de uma pasta. A partir desse script, você criará
uma ferramenta de script que pode ser facilmente compartilhada com outras pessoas.
A ferramenta que você irá desenvolver deve se parecer com a figura abaixo. Ela possui
dois parâmetros de entrada e nenhum parâmetro de saída. Os dois parâmetros de entrada
são:
• Uma pasta no disco contendo os conjuntos de dados vetoriais a serem
reprojetados.
• O caminho para um conjunto de dados vetoriais cuja referência espacial será
usada como padrão. Por exemplo, se você quiser reprojetar SIRGAS2000 UTM Zona 23,
você procuraria algum conjunto de dados vetoriais com este sistema de projeção. Este
poderia ser um dos conjuntos de dados na pasta que você forneceu no primeiro
parâmetro, ou poderia existir em outro lugar no disco.
81
mensagem, não uma mensagem por conjunto de dados reprojetado. Observe um
exemplo desse tipo de mensagem personalizada abaixo na linha "Reprojetados...":
Seu script deve relatar uma mensagem de geoprocessamento informando quais conjuntos de
dados foram projetados
• Não deve conter nenhum valor codificado diretamente no script, como nomes
de conjunto de dados, nomes de caminho ou nomes de projeção.
• Deve ser disponibilizado como uma ferramenta de script que pode ser
facilmente executada a partir do ArcToolbox por alguém sem conhecimento de scripts.
Esforços adicionais poderiam incluir o seguinte:
• Sua mensagem de geoprocessamento de conjuntos de dados projetados
contém vírgulas entre os nomes dos conjuntos de dados, sem nenhuma vírgula "final" no
final.
• A documentação de ajuda do painel lateral é fornecida para sua ferramenta de
script. Isso significa que quando você abre a caixa de diálogo da ferramenta e clica em
Mostrar Ajuda, as instruções para cada parâmetro aparecem ao lado. A Ajuda do ArcGIS
Desktop pode te ensinar como fazer isso.
• Sua ferramenta de script usa caminhos relativos ao arquivo .py e é facilmente
implantada sem ter que "reorientar" a caixa de ferramentas para o script.
Não vamos manipular transformações de datum neste script. Assume-se que cada
conjunto de dados na pasta usa o mesmo datum, embora os conjuntos de dados possam
estar em projeções diferentes. O tratamento de datum faria com que você tivesse que
adicionar um parâmetro adicional na ferramenta.
Dados para o projeto
A pasta de dados contém um conjunto de shapefiles vetoriais para você trabalhar neste
projeto e encontra-se no diretório c:\SEA5923\Dados\Shapefiles. Para o propósito deste
projeto esses conjuntos de dados estão com os sistemas de referência
GCS_Corrego_Alegre ou Corrego_Alegre_UTM_Zone_23S. Esses sistemas compartilham
o mesmo datum (Córrego Alegre) para que você não tenha que lidar com transformações de
datum. Os dados reprojetados devem ser salvos
O conjunto de dados vetoriais cuja referência espacial será usada como padrão estará
em C:\SEA5923\Dados\Shapefiles\Projetados. Esta classe de feições é um shapefile
Bacia_Onca.shp com o sistema de referência Corrego_Alegre_UTM_Zone_23S. Este
diretório também pode ser utilizado para armazenar os resultados.
Entregas
82
Entregas para este projeto são as seguintes:
O arquivo .py de origem contendo seu script
O arquivo .tbx contendo sua ferramenta de script
Um curto resumo (cerca de 300 palavras) descrevendo como você abordou o projeto,
como você lidou com os obstáculos e com o que aprendeu ao longo da tarefa.
Dicas
As dicas a seguir podem ajudar a melhorar sua possibilidade de sucesso com este
projeto:
• Não use a ferramenta ESRI Batch Project neste projeto. Em essência, você é
obrigado a fazer sua própria variação de uma ferramenta de projeção em lote neste
projeto, executando a ferramenta Project dentro de um loop. Sua ferramenta será mais
fácil de usar porque é personalizada para a tarefa em questão.
• Existem várias maneiras de inserir "_projetado" no nome de um conjunto de
dados, mas você pode achar útil começar removendo temporariamente a extensão ".shp"
e adicioná-lo novamente mais tarde. Para fazer seu código funcionar tanto para um
shapefile (que possui a extensão .shp) quanto para uma classe de feições em um
geodatabase (que não possui a extensão .shp), você pode usar o seguinte:
nomeOriginal = fc
if nomeOriginal.endswith (".Shp"):
nomeOriginal = nomeOriginal.replace (".Shp", "")
No código acima, “fc” é o nome da sua classe de feições. Se for o nome de um
shapefile, ele incluirá o .shp. A função replace procura por qualquer string ".shp" (o primeiro
parâmetro) no nome do arquivo e a substitui por nada (simbolizado no segundo parâmetro
por aspas vazias ""). Portanto, após executar este código, a variável “nomeOriginal” conterá
o nome da classe de feições sem o ".shp". Como a função replace(..) não muda nada se a
string dada como o primeiro parâmetro não ocorrer em fc, o código acima pode ser
substituído por apenas uma única linha:
nomeOriginal = fc.replace (".shp", "")
Você também pode potencialmente cortar os últimos quatro caracteres usando algo
como
nomeOriginal = fc[: -4]
mas os números de código diferentes de 0 ou 1 em seu script podem tornar o código
menos legível para outra pessoa. Ver uma função como substituir é muito mais fácil para
alguém interpretar do que ver -4 e tentar descobrir por que esse número foi escolhido.
Portanto, você deve usar replace(..) em sua solução.
• Para verificar se um conjunto de dados já está na projeção padrão, você precisará obter
um objeto de Referência Espacial para cada conjunto de dados (o conjunto de dados a
ser reprojetado e o conjunto de dados padrão). Você precisará comparar os nomes de
referência espacial desses dois conjuntos de dados. Não deixe de comparar a
propriedade Name das referências espaciais; não compare os próprios objetos de
referência espacial. Isso ocorre porque você pode ter dois objetos de referência espacial
que são entidades diferentes (e, portanto, "não iguais"), mas possuem a mesma
propriedade de nome.
Você deve acabar com uma linha semelhante a esta:
83
if fcSR.Name != srPadrao.Name:
em que fcSR é a referência espacial da classe de feições a ser projetada e srPadrao é
a referência espacial padrão obtida do arquivo indicado nos parâmetros da ferramenta.
• Se você quiser mostrar todas as mensagens de cada execução da ferramenta Project,
adicione a linha: arcpy.AddMessage (arcpy.GetMessages()) imediatamente após a linha
na qual você executa a ferramenta Project. Cada vez que o loop é executado, ele
adicionará as mensagens da execução atual da ferramenta Project na janela de
resultados. Tem sido minha experiência que, se você esperar para adicionar esta linha
até o final do seu script, você só receberá as mensagens da última execução da
ferramenta, por isso é importante colocar a linha dentro do loop. Lembre-se de que,
enquanto você escreve seu script pela primeira vez, é possível usar instruções de
impressão para depuração e, em seguida, alternar para arcpy.AddMessage() quando
verificar que o script funciona e está pronto para criar uma ferramenta de script.
• Se você precisar de ajuda extra para criar a ferramenta de script, leia Zandbergen 13.1 -
13.10.
• Se, após todos os seus esforços, você ficar sem tempo e não puder atender a um dos
requisitos, comente no código que não está funcionando (usando um sinal # no início de
cada linha) e envie o código mesmo assim. Em seguida, explique em sua breve descrição
qual seção não está funcionando e quais problemas você encontrou.
84
Etapa 3: Acesso e manipulação de dados SIG com o Python
Uma parte essencial de um SIG são os dados que representam a geometria
(localizações) de feições geográficas e os atributos dessas feições. Essa combinação de
feições e atributos é o que faz o SIG ser mais do que um simples "mapeamento". Muito do
seu trabalho como um analista SIG envolve adicionar, modificar e excluir feições e seus
atributos em um SIG.
Além da manutenção os dados, você também precisa saber como consultar e
selecionar dados mais importantes para seus projetos. Às vezes, você desejará consultar
um conjunto de dados para localizar somente os registros que correspondem a um
determinado critério (por exemplo, setores censitários com renda per capita abaixo de
determinado valor) e calcular algumas estatísticas com base apenas nos registros
selecionados (por exemplo, porcentagem desses setores com coleta de esgoto sanitário).
Todas as tarefas acima de manutenção, consulta e estatística de dados podem se
tornar tediosas e propensas a erros se executadas manualmente. O script em Python
geralmente é uma maneira mais rápida e precisa de ler e gravar grandes quantidades de
dados. Já existem muitas ferramentas para seleção e gerenciamento de dados no
ArcToolbox. Qualquer uma dessas pode ser usada em um script Python. Para cenários mais
personalizados em que você deseja ler uma tabela por conta própria e modificar registros
um a um, o arquivo arcpy contém objetos especiais, chamados cursores, que você pode
usar para examinar cada registro em uma tabela. Você verá rapidamente como a lógica de
loop que você aprendeu na etapa 2 se torna útil quando você percorre tabelas usando
cursores.
Usar um script para trabalhar com seus dados apresenta algumas outras vantagens
sutis sobre a entrada manual de dados. Por exemplo, em um script, você pode adicionar
verificações para garantir que os dados inseridos estejam em conformidade com um
determinado formato. Você também pode encadear várias etapas da lógica de seleção que
seriam demoradas para serem executadas no ArcMap.
Esta etapa explica maneiras de ler e gravar dados SIG usando o Python. Começaremos
analisando como você pode criar e abrir conjuntos de dados em um script. Em seguida,
praticaremos a leitura e a gravação de dados usando ferramentas de geoprocessamento e
objetos de cursor. Embora isso seja mais aplicável a conjuntos de dados vetoriais, também
veremos algumas maneiras de manipular rasters com o Python. Uma vez que você esteja
familiarizado com esses conceitos, o Projeto 3 lhe dará a chance de praticar o que você
aprendeu.
Objetivos da etapa 3
85
• Entender o conceito de layers, como as eles podem ser criados e como realizar a seleção
por local com layers
• Ser capaz de escrever scripts ArcGIS que resolvam tarefas comuns com dados vetoriais,
combinando seleção por atributo, seleção por localização e manipulação de tabelas de
atributos via cursores
86
em conjuntos de dados de feições (Feature Datasets). Conjuntos de dados raster também
podem ser armazenados em geodatabases.
Conjuntos de dados independentes
Embora os bancos de dados geográficos sejam essenciais para o armazenamento e a
organização de dados a longo prazo, às vezes é conveniente acessar conjuntos de dados
em um formato "independente" no sistema de arquivos local. O shapefile da ESRI é
provavelmente o formato de dados vetoriais mais onipresente e autônomo. Um shapefile na
verdade consiste em vários arquivos que trabalham juntos para armazenar geometrias e
atributos vetoriais. Todos os arquivos têm o mesmo nome raiz, mas usam extensões
diferentes. Você pode compactar os arquivos juntos e enviá-los por e-mail facilmente ou
publicá-los em uma pasta para download. Nos navegadores de arquivos ESRI no ArcCatalog
ou no ArcMap, os shapefiles aparecem apenas como um arquivo.
Nota:
Às vezes, na documentação da ESRI shapefiles também são chamados de "classes
de feições". Quando você vê o termo "classe de feições", considere que isso significa um
conjunto de dados vetoriais que pode ser usado no ArcGIS.
Outro tipo de conjunto de dados independente que remonta aos primórdios do ArcGIS
é a coverage do ArcInfo. Como o shapefile, a coverage consiste em vários arquivos que
funcionam juntos. As coverages estão se tornando cada vez mais raras, mas você pode
encontrá-las se sua organização tiver usado (ou ainda usar!) Workstagion ArcInfo.
Conjuntos de dados raster também são frequentemente armazenados em formato
independente, em vez de serem carregados em um geodatabase. Um conjunto de dados
rasterizados pode ser um único arquivo, como JPEG ou TIFF, ou, como um shapefile, pode
consistir em vários arquivos que funcionam juntos.
Fornecendo caminhos em scripts do Python
Muitas vezes, em um script, você precisará fornecer o caminho para um conjunto de
dados. Conhecer a sintaxe para especificar o caminho às vezes é um desafio por causa das
muitas maneiras diferentes de armazenar os dados listados acima. Por exemplo, abaixo está
um exemplo de como um arquivo geodatabase se parece se você simplesmente navega
pelo sistema de arquivos do Windows Explorer. Como você especifica o caminho para o
conjunto de dados necessário? Esse mesmo desafio pode ocorrer com um shapefile, que,
embora tenha um nome mais intuitivo, possui três ou mais arquivos participantes.
87
caminho destacado mostra como você se referiria a uma classe de feições dentro do
geodatabase.
88
Aqui está um código que filtra cada classe de feição em um arquivo geodatabase para
o limite de estado do Alabama e coloca a saída em um arquivo geodatabase diferente.
Observe como as cinco linhas de código após a importação correspondem às cinco etapas
listadas acima.
import arcpy
arcpy.env.workspace = "C:\\SEA5923\\Dados\\FC\\FC.gdb"
featureClassList = arcpy.ListFeatureClasses()
clipFC = "
C:\\SEA5923\\Dados\\FC\\Resultados\\FC_Clip.gdb\\Consorcio_mun"
for fc in fcList:
arcpy.Clip_analysis(fc, clipFC,
"C:\\SEA5923\\Dados\\FC\\Resultados\\FC_Clip.gdb" + fc)
No exemplo acima, o método arcpy.ListFeatureClasses() foi a chave para fazer a lista.
Esse método examina um local de trabalho e cria uma lista Python de cada classe de feições
nesse local de trabalho. Depois de ter essa lista, você pode configurar facilmente um loop
para agir em cada item.
Observe que você designou o caminho para o espaço de trabalho usando o local do
arquivo geodatabase. Se você estivesse trabalhando com shapefiles, usaria apenas o
caminho para a pasta como o local de trabalho.
Se você estivesse trabalhando com o ArcSDE, usaria o caminho para o arquivo de
conexão .sde ao criar seu local de trabalho. Este é um arquivo que é criado quando você se
conecta ao ArcSDE no ArcCatalog e é colocado em seu diretório de perfil local. Nós não
estaremos acessando os dados em ArcSDE neste curso.
89
Acessando campos da tabela de atributos
Antes de nos aprofundarmos no acesso a dados vetoriais, será útil revisar rapidamente
como os dados vetoriais são armazenados no software. As feições de vetor nas classes de
feições do ArcGIS (usando este termo para incluir shapefiles) são armazenados em uma
tabela. A tabela possui linhas (registros) e colunas (campos).
Campos da tabela de atributos
Os campos na tabela armazenam as informações de geometria e atributos para as
feições.
Existem dois campos na tabela que você não pode excluir. Um dos campos
(geralmente chamado de Shape) contém as informações de geometria para as feições. Isso
inclui as coordenadas de cada vértice da feição e permite que ela seja desenhada na tela. A
geometria é armazenada em formato binário; se você fosse vê-lo impresso na tela, não faria
sentido para você. No entanto, você pode ler e trabalhar com as geometrias usando objetos
que são fornecidos com o arcpy.
O outro campo incluído em cada classe de feições é um campo de ID de objeto
(OBJECTID ou FID). Contém um número único ou identificador para cada registro que é
usado pelo ArcGIS para rastrear as feições. O ID do objeto ajuda a evitar confusão ao
trabalhar com dados. Às vezes, os registros possuem os mesmos atributos. Por exemplo,
São Paulo e São Carlos podem ter um atributo Estado = "SP" ou um conjunto de dados de
cidades no Brasil pode mais de uma cidade com o atributo NOME = "São Carlos". no entanto,
o campo OBJECTID nunca pode ter o mesmo valor para dois registros.
O restante dos campos contém informações sobre atributos que descrevem a feição.
Esses atributos geralmente são armazenados como números ou texto.
Descobrindo os nomes dos campos
Quando você escreve um script, você precisa fornecer os nomes dos campos
específicos que deseja ler ou escrever. Você pode obter uma lista Python de nomes de
campos usando arcpy.ListFields().
# Lendo os nomes dos campos da tabela de atributos de uma FC
import arcpy
featureClass = "C:\SEA5923\Dados\BaseDados.gdb\Municipios"
fieldList = arcpy.ListFields(featureClass)
# Percorrendo a lista de campos da TA e escrevendo o nome de cada campo
for field in fieldList:
print (field.name)
O texto acima produziria uma lista dos campos da classe de feições Cidades em um
arquivo geodatabase chamado USA.gdb. Se você executou este script no PythonWin
(experimente com outras classes de feições!), você verá algo como o seguinte na Janela
Interativa.
>>> OBJECTID
Shape
GEOCODIGO
NOME
UF
REGIAO
MESOREGIAO
AREA_KM²
90
Shape_Length
Shape_Area
Observe os dois campos especiais sobre os quais já falamos: “OBJECTID”, que contém
o número de identificação exclusivo de cada registro, e “Shape”, que contém a geometria do
registro. Além disso, essa classe de feições possui campos que contêm o nome (NOME), o
estado (UF), o geocódigo do IBGE (GEOCODIGO) e assim por diante.
arcpy trata o campo como um objeto, portanto, Field tem propriedades que o
descrevem. É por isso que você pode imprimir field.name. O tópico de referência de ajuda
Usando campos e índices (http://desktop.arcgis.com/en/arcmap/latest/analyze/python/fields-
and-indexes.htm) lista todas as propriedades que você pode ler em um campo. Estes
incluem AliasName, Lenght, Type, Scale, e outros.
As propriedades de um campo são somente leitura, o que significa que você pode
descobrir quais são as propriedades do campo, mas não é possível alterar essas
propriedades em um script usando o objeto Field. Se você quisesse alterar a escala e a
precisão de um campo, por exemplo, teria que adicionar programaticamente um novo
campo.
91
• Use o código SearchCursor.next() para ler a primeira linha.
• Inicie um loop que sairá quando não houver mais linhas disponíveis para leitura.
• Faça algo com os valores na linha atual.
• Use o código SearchCursor.next() para ir para a próxima linha. Como você criou um loop,
isso o coloca de volta na etapa anterior, se houver outra linha disponível para leitura. Se
não houver mais linhas, a condição de loop não será atendida e o loop será finalizado.
Quando você tenta primeiro entender os cursores, pode ajudar a visualizar a tabela de
atributos com uma seta apontando para a "linha atual". Quando o cursor é criado pela
primeira vez, essa seta está apontando logo acima da primeira linha da tabela. Na primeira
vez que o método next() é chamado, a seta se move para a primeira linha (e retorna uma
referência a essa linha). Cada vez que next() é chamado, a seta desce uma linha. Se next()
for chamado quando a seta estiver apontando para a última linha, um tipo de dado especial
chamado None será retornado.
Aqui está um exemplo muito simples de um cursor de pesquisa que lê um conjunto de
dados de pontos que correspondem aos postos pluviométricos e imprime o nome de cada
um deles.
# Imprime o nome de cada feature class
import arcpy
featureClass = "C:\\SEA5923\\Dados\\Plu_Total_Anual.shp"
linhas = arcpy.SearchCursor(featureClass)
linha = linhas.next()
while linha:
print (linha.NAME)
linha = linhas.next()
As últimas cinco linhas do script acima correspondem às cinco etapas do fluxo de
trabalho acima. Cursores podem ser difíceis de entender no início, então vamos olhar para
essas linhas mais de perto. Abaixo estão as cinco linhas novamente com comentários para
que você possa ver exatamente o que está acontecendo:
# Imprime o nome de cada feature class
import arcpy
featureClass = "C:\\SEA5923\\Dados\\Plu_Total_Anual.shp"
# Cria o cursor de pesquisa
linhas = arcpy.SearchCursor(featureClass)
# Usa o searchCursor.next() para ler a primeira linha
linha = linhas.next()
# Inicia o loop que irá terminar quando não tivermos mais linhas
while linha:
# Faz alguma coisa com o valor da linha atual
print (linha.Nome)
# Usa o searchCursor.next() para mover para a próxima linha
linha = linhas.next()
Observe algumas outras coisas importantes antes de prosseguir:
• A condição de loop "while row:" é uma maneira booleana simples de especificar se o loop
deve continuar. Se um objeto de linha existir, a instrução será avaliada como verdadeira
e o loop continuará. Se um objeto de linha não existir, a instrução será avaliada como
falsa e o loop será finalizado.
92
• Você pode ler um valor de campo como uma propriedade de uma linha. Por exemplo,
linha.Nome forneceu o valor no campo Nome. Se sua tabela tivesse um campo Codigo,
você poderia usar linha.Codigo para obter o código.
• Os nomes "linhas" e "linha" são apenas nomes de variáveis que representam os objetos
SearchCursor e Row, respectivamente. Nós poderíamos nomear com qualquer termo.
Os exemplos ESRI tendem a nomeá-los como Rows e Row, e faremos o mesmo. No
entanto, se você precisasse usar dois cursores de pesquisa ao mesmo tempo, teria que
criar alguns nomes adicionais.
Aqui está outro exemplo em que algo mais complexo é feito com os valores da linha.
Este script encontra a precipitação média em um conjunto de dados. Para encontrar a média,
você precisa dividir a precipitação total pelo número de postos pluviométricos. O código
abaixo percorre cada registro e mantém um total da precipitação e o número de registros
contados. Uma vez que todos os registros foram lidos, apenas uma linha de divisão é
necessária para encontrar a média.
# Encontra a precipitação média em um conjunto de postos pluviométricos
import arcpy
postosPlu = "C:\\SEA5923\\Dados\\Plu_Total_Anual.shp"
linhas = arcpy.SearchCursor(postosPlu)
linha = linhas.next()
media = 0
precipitacaoTotal = 0
contador = 0
# Loop pelos registros e cálculo do total precipitado e contador
while linha:
precipitacaoTotal += linha.Total_2018
contador += 1
linha = linhas.next()
media = precipitacaoTotal / contador
print ("Média da precipitação " + str(media))
Embora o script acima seja maior do que o primeiro, ele ainda segue o padrão geral de
criação de um cursor de pesquisa, avançando para a primeira linha, fazendo algo com a
linha e repetindo o processo até que não haja registros restantes.
Lendo valores quando o nome do campo é uma variável
No script anterior, a precipitação de um registro era referenciada como
linha.Total_2018, em que o nome do campo de precipitação é Total_2018. Esta é uma
maneira muito fácil de obter um valor de campo, mas o que acontece se você quiser obter
dados para 2019 em um campo chamado Total_2019 e quiser executar o script novamente?
E se você tiver muitos scripts longos que sempre fazem referência ao campo precipitação
dessa maneira? Você teria que pesquisar cuidadosamente cada script para linha.Total_2018
e substituí-lo por linha.Total_2019 . Isso pode ser tedioso e propenso a erros.
Você pode tornar seus scripts mais versáteis usando variáveis para representar nomes
de campos. Você pode declarar uma variável, como campoPrecipitacao, para fazer
referência ao nome do campo da precipitação, seja Total_2018, Total_2019 ou
simplesmente PRECIPITACAO. O interpretador Python não irá reconhecer
linha.campoPrecipitacao, então você precisa usar linha.getValue() e passar a variável
como um parâmetro.
93
O script abaixo usa um nome de variável para obter a precipitação de cada registro. As
linhas alteradas do script acima têm um comentário acima delas "# Esta linha abaixo é nova".
Observe como uma variável denominada campoPrecpitacao é criada e o método chama
linha.getValue(campoPrecpitacao)que recupera a precipitação de cada registro.
94
media = precipitacaoTotal / contador
print ("Média da precipitação " + str(media))
Veja como você pode executar o script acima em PythonWin, fornecendo o nome do
caminho e o campo de precipitação como os argumentos.
95
Se você estiver usando o ArcGIS 10.1 ou superior, você pode usar o código acima para
cursores de busca, ou você pode usar um novo módulo de acesso a dados que foi
introduzido no arcpy. Essas funções de acesso a dados são prefixadas com arcpy.da e
oferecem um desempenho mais rápido, juntamente com um comportamento mais robusto,
quando falhas ou erros são encontrados no cursor.
O módulo de acesso a dados arcpy.da permite que você crie objetos de cursor, assim
como o arcpy, mas você os cria de forma um pouco diferente. Observe atentamente o código
de exemplo a seguir, que repete o cenário acima para calcular a precipitação média.
# coding: utf-8
# Encontra a precipitação média em um conjunto de postos pluviométricos
import arcpy
postosPlu = arcpy.GetParameterAsText(0)
campoPrecipitacao = arcpy.GetParameterAsText(1)
media = 0
precipitacaoTotal = 0
contador = 0
with arcpy.da.SearchCursor(postosPlu, (campoPrecipitacao,)) as cursor:
for linha in cursor:
precipitacaoTotal += linha[0]
contador += 1
media = precipitacaoTotal / contador
print ("Média da precipitação " + str(media))
Este exemplo usa a mesma estrutura básica que a anterior, com algumas alterações
importantes. Uma coisa que você provavelmente notou é que o cursor é criado usando uma
instrução "with". Embora a explicação de "with" seja um pouco técnica, a principal coisa a
ser entendida é que ela permite que o cursor saia do conjunto de dados normalmente,
independentemente de travar ou concluir seu trabalho com êxito.
A instrução "with" requer que você indente todo o código abaixo dela. Depois de criar
o cursor em sua instrução "with", você iniciará um loop for para percorrer todas as linhas da
tabela. Isso requer recuo adicional.
Observe que essa instrução "with" cria um objeto SearchCursor e declara que ele será
nomeado "cursor" em qualquer código subseqüente. Os cursores de busca criados com o
arcpy.da possuem alguns parâmetros de inicialização diferentes dos cursores de pesquisa
criados com o arcpy. A maior diferença é que quando você cria um cursor com arcpy.da,
você precisa fornecer uma tupla de nomes de campos que serão retornados pelo cursor.
Lembre-se de que uma tupla é uma estrutura de dados do Python muito parecida com uma
lista, exceto que ela é colocada entre parênteses e seu conteúdo não pode ser modificado.
Fornecer essa tupla acelera o trabalho do cursor porque ele não precisa lidar com as
potencialmente dezenas de campos incluídos em seu conjunto de dados. No exemplo acima,
a tupla contém apenas um campo, campoPrecipitacao. Uma tupla com apenas um item
contém uma vírgula após o item, portanto, nossa tupla acima é semelhante a:
(campoPrecipitacao,). Se a tupla tivesse vários itens, poderíamos ver algo como:
(campoPrecipitacao, campoNome).
Observe que com arcpy.da, você usa objetos de linha como com arcpy; no entanto,
você não usa o método getValue para recuperar valores das linhas. Em vez disso, você usa
a posição do índice do nome do campo na tupla que você enviou quando criou o objeto.
Como o exemplo acima submete apenas um item na tupla, a posição do índice de
campoPrecipitacao dentro dessa tupla é 0 (lembre-se de que começamos a contar a partir
96
de 0 no Python). Portanto, você pode usar linha[0] para obter o valor de campoPrecipitacao
para uma linha específica.
Como a maioria dos estudantes atualmente usa o ArcGIS versões superiores a10.1, os
exemplos deste ponto em diante usam o módulo arcpy de acesso a dados. Vale a pena
concentrar-se nas funções do arcpy.da porque ele tornará seu código mais rápido, mais
compacto e mais robusto. Você é obrigado a usar o arcpy.da em seu código de projeto da
etapa 3.
97
Depois de recuperar o subconjunto de registros, você pode seguir o mesmo padrão de
iteração através deles usando um loop for.
with arcpy.da.SearchCursor(postosPlu, (campoPrecipitacao,), '"Total_2018"
> 1000') as cursor:
for linha in cursor:
print (str(linha[0]))
Manipulando as aspas
Quando você inclui uma expressão SQL em seu construtor SearchCursor, deve
fornecê-la como uma string. É aqui que as coisas podem ficar complicadas com as aspas.
O SQL exige aspas simples e duplas em locais específicos, mas também é necessário incluir
a expressão inteira entre aspas, porque é uma string. Como você evita ficar confuso?
No Python, você pode usar aspas simples ou aspas duplas para incluir uma string.
Você deve ter notado que no exemplo acima, coloquei a expressão SQL entre aspas simples,
e não aspas duplas: '"Total_2018">1000'. Como eu sabia que as aspas duplas seriam
necessárias na instrução SQL (para cercar o nome do campo), usei aspas simples para
cercar a string inteira. Isto não é apenas para manter as coisas fáceis de ler; se eu tivesse
usado duas aspas duplas em uma linha, o interpretador Python ficaria confuso e pensaria
que eu estava criando uma string vazia. Portanto, não foi uma opção usar
""Total_2018">1000".
A situação fica mais difícil quando sua expressão SQL deve usar aspas simples e
duplas, por exemplo, quando você consulta uma variável de string. Suponha que seu script
permita que o usuário insira o ID de um posto Plu e você precise encontrá-lo com um cursor
de pesquisa. \supondo que alguns dos IDs dos postos incluem letras e outros não, portanto,
você precisa sempre tratar o ID dos postos como uma string. Sua expressão SQL
provavelmente ficaria assim: "codigo" = 'PLU0001'. Essa expressão começa com aspas
duplas e termina com aspas simples, portanto, qual estilo de aspas você usa para delimitar
toda a expressão?
Nesse caso, você não pode simplesmente colocar a expressão inteira em um estilo de
aspas; você precisa dividir a expressão em strings separadas. Veja de perto este exemplo:
ID = arcpy.GetParameterAsText(0)
expressaoSQL = '"codigo"' + " = '" + str(ID) + "'"
with arcpy.da.SearchCursor(postosPlu, (campoCodigo,), expressaoSQL) as
cursor:
...
No código acima, a variável expressaoSQL, ou a expressão SQL, é criado em partes
gerenciáveis que não misturam aspas simples e duplas. Se a parte da expressão contiver
aspas duplas, como "codigo", ela estará entre aspas simples. Se a parte da expressão
contiver aspas simples, como = ' ou apenas ', ela estará entre aspas duplas. Esse tipo de
situação é onde pode ser útil incluir temporariamente uma instrução print em seu código ou
usar as ferramentas de depuração para garantir que a variável expressaoSQL seja
construída corretamente. Pode ser útil se você puder treinar seu olho para se concentrar no
sinal + como um separador entre todas as partes independentes da sequência que você está
construindo.
Delimitadores de campo
Nos exemplos acima, os nomes de campo estão entre aspas duplas (por exemplo,
"codigo"). Esta é a sintaxe correta para shapefiles e file geodatabases, que são os únicos
tipos de dados que usaremos neste curso. Se você usa personal geodatabases em seu
98
trabalho diário, existem diferentes maneiras de delimitar o nome do campo. Se você estiver
interessado na sintaxe correta para diferentes tipos de dados, ou em maneiras de tornar seu
script flexível para qualquer tipo de dados, dê uma olhada no tópico Referência SQL para
expressões de consulta usadas no ArcGIS na Ajuda do ArcGIS Desktop.
http://desktop.arcgis.com/en/arcmap/latest/map/working-with-layers/sql-reference-for-
query-expressions-used-in-arcgis.htm
99
• Abra um cursor de pesquisa na camada todosEstados. O cursor incluirá apenas São
Paulo e os estados que o tocam, porque há uma seleção aplicada à essa camada.
Lembre-se de que a camada de feição é apenas um conjunto de registros mantidos na
memória. Mesmo se você chamar a camada todosEstados, ela não incluirá mais todos
os estados depois que você aplicar uma seleção.
arcpy.SelectLayerByLocation_management("todosEstados","BOUNDARY_TOUCHES",
"layerSelEstados")
# Abre um search cursor
with arcpy.da.SearchCursor("todosEstados", (nomeCampo,)) as cursor:
for linha in cursor:
# Print o nome de todos os estados da seleção
print (linha[0])
except:
print (arcpy.GetMessages())
finally:
# Limpa as camadas de feições e o cursor
arcpy.Delete_management("todosEstados")
arcpy.Delete_management("layerSelEstados")
del cursor
Você pode escolher entre vários operadores espaciais ao executar o
SelectLayerByLocation. O código acima usa "BOUNDARY_TOUCHES". Outros
relacionamentos disponíveis são "INTERSECT", "WITHIN A DISTANCE" (você pode salvar
uma etapa de armazenamento em buffer), "CONTAINS", "CONTAINED_BY" e outros.
Observe que o objeto Row "linha" retorna apenas um campo ("NOME"), que é
acessado usando sua posição de índice na lista de campos. Como há apenas um campo,
esse índice é 0 e a sintaxe é semelhante a: linha[0]. Depois de abrir o cursor de pesquisa
nos registros selecionados, você poderá executar qualquer ação que desejar. O código
acima apenas imprime o nome do estado, mas é mais provável que você queira resumir ou
atualizar os valores dos atributos. Você aprenderá a escrever valores de atributos
posteriormente nesta lição.
100
Limpando camadas de feições e cursores
Observe que as camadas de feições são excluídas usando a ferramenta Delete. Isso
ocorre porque as camadas de feições podem ocacionar bloqueios em seus dados,
impedindo que outros aplicativos usem os dados até que seu script seja concluído. O Arcpy
deve limpar as camadas de feições no final do script, mas é uma boa idéia excluí-las você
mesmo, caso isso não aconteça ou caso ocorra uma falha. Nos exemplos acima, o bloco
except é acionado no caso de uma falha, então o script continuará e executará a ferramenta
Delete.
Cursores também podem manter bloqueios nos dados. Como mencionado
anteriormente, a instrução "with" deve limpar o cursor automaticamente para você. No
entanto, descobrimos que nem sempre, uma observação que parece ser apoiada por esta
sinopse da documentação da ESRI da classe arcpy.da.SearchCursor.
http://desktop.arcgis.com/en/arcmap/latest/analyze/arcpy-data-access/searchcursor-
class.htm
Os cursores de pesquisa também suportam instruções para redefinir a iteração e
ajudam na remoção de bloqueios. No entanto, usar uma instrução del para excluir o objeto
ou envolver o cursor em uma função para que o objeto do cursor fique fora de escopo deve
ser considerado para proteger contra todos os casos de bloqueio.
Um último ponto a relatar sobre este código que limpa as camadas de feições e o cursor
é que ele é incorporado dentro de um bloco finally. Essa é uma construção que é usada
ocasionalmente com try e except para definir o código que deve ser executado,
independentemente de as instruções no bloco try serem executadas com êxito. Para
entender a utilidade do bloco finally, imagine se você tivesse colocado essas instruções de
limpeza no final do bloco try. Se um erro ocorrer em algum lugar acima desse ponto no bloco
try - não é difícil imaginar, certo? - o restante do bloco try não seria executado, deixando as
camadas de feições e o cursor na memória. Uma execução subseqüente do script, após
corrigir o erro, encontraria um novo problema: o script não poderia criar a camada de feições
chamada "todosEstados" porque ela já existiria. Em outras palavras, as instruções de
limpeza só seriam executadas se o restante do script fosse executado com êxito.
Esta situação é onde a declaração finally é especialmente útil. O código em um bloco
finally será executado independentemente de algo no bloco try disparar uma falha. (No caso
de um erro ser encontrado, o código final será executado após o bloco except.) Assim,
conforme você desenvolve seu próprio código utilizando camadas de feição e / ou cursores,
é uma boa idéia incluir essas instruções de limpeza em um bloco finally.
Leitura obrigatória
Examine as seguintes páginas de referência de ferramentas. Você pode ignorar a
seção Sintaxe da Linha de Comando, mas preste atenção particular às Dicas de Uso e aos
Exemplos de Script.
• Make a Feature Layer
http://desktop.arcgis.com/en/arcmap/latest/tools/data-management-toolbox/make-
feature-layer.htm
• Select Layer By Location
http://desktop.arcgis.com/en/arcmap/latest/tools/data-management-toolbox/select-layer-
by-location.htm
• Select Layer By Attribute
101
• http://desktop.arcgis.com/en/arcmap/latest/tools/data-management-toolbox/select-layer-
by-attribute.htm
102
• Modifique os valores do campo na linha que precisam de atualização (veja abaixo).
• Chame UpdateCursor.updateRow() para finalizar a edição.
103
de campoAfetado), portanto, sua posição de índice é 0 na tupla. Portanto, você define esse
valor de campo usando linha[0] = valorNovo . A limpeza do cursor não é necessária no final
do script porque isso é realizado por meio da instrução "with".
A última linha com updateRow(..) é necessária para garantir que a linha modificada
seja realmente gravada de volta na tabela de atributos. Por favor, note que a linha variável
precisa ser passada como um parâmetro para updateRow(linha).
Para testar este script utilize a classe de feições de postos pluviométricos, o campo
“orgao” e substitua o valor de “ANA” para “SANEPAR” por exemplo.
C:\SEA5923\Dados\PostosPLU.shp
Bloqueio do conjunto de dados
Como mencionamos, o ArcGIS às vezes bloqueia os conjuntos de dados para evitar a
possibilidade de conflitos entre dois usuários. Se por algum motivo você acha que um
bloqueio do seu script está afetando seu conjunto de dados (impedindo que você o visualize,
fazendo com que pareça que todas as linhas foram excluídas etc.), é necessário fechar o
PythonWin para remover o bloqueio. Se você acha que o ArcGIS tem um bloqueio em seus
dados, verifique se o ArcMap ou o ArcCatalog estão usando os dados de alguma forma. Isso
pode ocorrer por meio de uma sessão de edição aberta nos dados, com os dados abertos
na guia Visualizar no ArcCatalog ou com a camada selecionada em um documento de mapa
aberto (MXD).
Como dissemos, a limpeza do cursor deve acontecer através da criação do cursor
dentro de uma instrução "with", mas adicionar linhas para excluir os objetos de linha e cursor
fará com que bloqueios com certeza sejam liberados.
Para entender como o bloqueio funciona, você pode revisar a seção "Cursores e
bloqueio" no tópico “Acessando dados usando cursores” na Ajuda do ArcGIS Desktop.
https://pro.arcgis.com/en/pro-app/arcpy/get-started/data-access-using-cursors.htm
104
with arcpy.da.InsertCursor (fc, ("Nome", "Sobrenome")) as cursor:
você adicionaria uma nova linha com os valores "Fulano" para "Nome" e "Sicrano" para
"Sobrenome" pelo seguinte comando:
cursor.insertRow(("Fulano", "Sicrano"))
Por favor, note que os parênteses internos são necessários para transformar os valores
em uma tupla que é passada para insertRow(). Escrevendo cursor.insertRow("Fulano",
"Sicrano") resultaria em um erro.
Exemplo
O exemplo abaixo usa um cursor de inserção para criar um novo ponto em um conjunto
de dados e atribuir um atributo a ele: uma descrição de string. Esse script poderia ser usado
por trás de um aplicativo no qual pessoas poderiam indicar as coordenadas e digitar uma
descrição de um incidente que precisa ser resolvido pelo município, como uma iluminação
quebrada, por exemplo.
# Adiciona um ponto e a sua descrição
import arcpy
# Valores de entrada
coorX = arcpy.GetParameterAsText(0)
coorY = arcpy.GetParameterAsText(1)
descricao = arcpy.GetParameterAsText(2)
# Parâmetros fixos, que o usuário não pode alterar
notificacaoFC = "C:/SEA5923/Dados/notificacoes.shp"
campoDescricao = "DESCR"
# Criando a tupla com os campos
camposAfetados = ("SHAPE@XY", campoDescricao)
# Criando o cursor
with arcpy.da.InsertCursor(notificacaoFC, camposAtefatos) as cursor:
# Inserindo a linha e informando a tupla de campos afetados
cursor.insertRow(((float(coorX),float(coorY)), descricao))
del cursor
Reserve um momento para garantir que você saiba exatamente como o seguinte é feito
no código:
• A criação do cursor de inserção com uma tupla de campos afetados armazenados na
variável campoAfetados
• A inserção da linha pelo método insertRow() usando variáveis que contêm os valores de
campo da nova linha
Se esse script estivesse realmente alimentando um aplicativo interativo, os valores X e
Y poderiam ser derivados de um ponto em que um usuário clicou em um mapa da Web, e
não como parâmetros, como feito no script.
Uma coisa que você deve ter notado é que a string "SHAPE@XY" é usada para
especificar o campo Shape. Você poderia esperar que isso fosse realizado apenas com
"Shape", mas o arcpy.da fornece uma lista de "tokens" que você pode usar se o campo for
especificado de uma determinada maneira. No nosso caso, seria muito conveniente apenas
fornecer os valores X e Y dos pontos usando uma tupla de coordenadas. Acontece que o
token "SHAPE@XY" permite que você faça exatamente isso. Veja o tópico de ajuda do
InsertCursor para aprender sobre outros tokens que você pode usar.
105
http://desktop.arcgis.com/en/arcmap/latest/analyze/arcpy-data-access/insertcursor-
class.htm
Colocando tudo isso junto, o exemplo cria uma tupla de campos afetados:
("SHAPE@XY", "DESCR"). Observe que, usamos realmente a variável campoDescricao
que contém o nome da segunda coluna "DESCR" para o segundo elemento da tupla. Usar
uma variável para armazenar o nome da coluna que nos interessa nos permite adaptar
facilmente o script mais tarde, por exemplo, a um conjunto de dados em que a coluna tem
um nome diferente. Quando a linha é inserida, os valores para esses itens são fornecidos
na mesma ordem: cursor.insertRow(((float(coorX), float(coorY)), descricao)). O
argumento passado para insertRow () é uma tupla que possui outra tupla (coorX, coorY), ou
seja, as coordenadas dos pontos, como o primeiro elemento e o texto para o campo
"DESCR" como o segundo elemento.
Leituras
Reserve alguns minutos para ler o Zandbergen 7.1 - 7.3 para reforçar seu aprendizado
sobre cursores.
106
desafio mesmo no ModelBuilder construir uma expressão flexível nas ferramentas de
álgebra do mapa. Com o Python, você pode manipular a expressão tanto quanto precisar.
Exemplo
Examine o exemplo a seguir, que recebe um valor mínimo e máximo de elevação como
parâmetros e faz alguma álgebra de mapa com esses valores. A expressão isola áreas em
que a elevação é maior que o parâmetro mínimo e menor que o parâmetro máximo. As
células que satisfazem a expressão recebem um valor de 1 pelo software e as células que
não satisfazem a expressão recebem um valor de 0.
Mas e se você não quiser que esses 0 valores bagunçam sua imagem? Este script
elimina os 0s executando a ferramenta Reclassify com uma tabela de remapeamento
simples informando que os valores de rasterização de entrada de 1 devem permanecer 1.
Como 0 é deixado de fora da tabela de remapeamento, ele é reclassificado como NoData:
# Este script pega um MNT e reclassifica as áreas entre uma
# valor min e max
import arcpy
from arcpy.sa import *
arcpy.env.overwriteOutput = True
arcpy.env.workspace = "C:/SEA5923/Dados"
# Parâmetros de elevação min e max
min = arcpy.GetParameterAsText(0)
max = arcpy.GetParameterAsText(1)
arcpy.CheckOutExtension("Spatial")
# Realiza a álgebra de mapa e cria um raster temporário
MDE = Raster("MDE_onca.tiff")
tempRaster = (MDE > int(min)) & (MDE < int(max))
# Configura a tabela de remapeamento e chama Reclassify, deixando todos
# os valores diferentes 1 como NODATA
tabela = RemapValue([[1,1]])
novoRaster = Reclassify(tempRaster, "Value", tabela, "NODATA")
# Salva o raster reclassificado no disco
novoRaster.save("MDE_onca_recl.tiff")
arcpy.CheckInExtension("Spatial")
Leia o exemplo acima cuidadosamente, quantas vezes forem necessárias para você
entender o que está ocorrendo em cada linha. Observe as seguintes coisas:
• Existe uma rasterização intermediária (em outras palavras, não a saída final) que você
não deseja ter no diretório de saída. Isso é chamado de tempRaster no script.
• Observe que a expressão contém sinais > e <, assim como o operador &. Você tem que
colocar cada lado da expressão entre parênteses para evitar confundir o operador &.
• Como temos arcpy.GetParameterAsText() para obter os parâmetros de entrada, é
necessário converter essas entradas em um inteiros antes de poder fazer a álgebra do
mapa com ela. Se usássemos apenas o min, o software veria "700", por exemplo, e
tentaria interpretá-lo como uma string. Para fazer a comparação numérica, temos que
usar int(min). Então o software vê o número 700 em vez da string "700".
• A álgebra de mapas pode executar muitos tipos de matemática e operações em rasters,
não limitadas a "maior que" ou "menor que". Por exemplo, você pode usar a álgebra de
mapa para encontrar o cosseno de um raster.
• Observe que o script não chama as funções de análise espacial usando arcpy. Em vez
disso, ele importa funções do módulo Spatial Analyst (arcpy.sa import *) e chama as
107
funções diretamente. Por exemplo, não vemos arcpy.Reclassify() ; em vez disso,
apenas chamamos Reclassify() diretamente.
• Consulte o tópico Remapear Classes na ajuda para entender como a tabela de
remapeamento neste exemplo foi criada. Sempre que você executar o Reclassify, será
necessário criar uma tabela de remapeamento indicando como os valores antigos devem
ser reclassificados para novos valores. Este exemplo tem a mais simples tabela de
remapeamento possível, mas se você quiser uma tabela de remapeamento mais
complexa, precisará estudar a documentação.
http://desktop.arcgis.com/en/arcmap/latest/analyze/arcpy-spatial-analyst/an-overview-
of-remap-classes.htm
Exercício 1
Neste exercício prático, você selecionará feições por localização e atualizará um
campo para as feições selecionados. Você também usará sua seleção para realizar um
cálculo.
Na sua pasta de dados, você tem um geodatabase BD.gdb com duas classes de
feições:
• Cidades - Contém os limites de polígonos das cidades do estado do ES.
• EstacoesFlu - contém feições de pontos que representam postos Fluviométricos.
O objetivo
Você quer descobrir quais cidades contêm postos fluviométricos e qual porcentagem
de cidades tem pelo menos um posto.
108
• A classe de feições Cidades tem um campo "estFlu", que é definido como “Falso” por
padrão. Seu trabalho é marcar esse campo como “Verdadeiro” para todas as cidades
que contenham pelo menos um posto fluviométrico dentro de seus limites.
• Seu script também deve calcular a porcentagem de cidades que têm postos
fluviométricos e imprimir esse número para o usuário.
Você não precisa criar uma ferramenta de script para essa atribuição. Você pode
codificar os valores das variáveis. Tente agrupar as variáveis de string codificadas no início
do script.
Dicas
Você pode pular para a tarefa neste momento ou ler as dicas a seguir para fornecer
algumas orientações.
• Crie duas camadas de feições: "cidadesLayer" e "postosFluLayer".
• Use SelectLayerByLocation com um tipo de relacionamento "CONTAINS" para restringir
a lista de camadas de feições de suas cidades a apenas as cidades que contêm postos
fluviométricos.
• Crie um cursor de atualização para "cidadesLayer" reduzido e faça um loop em cada
registro, configurando o campo estFlu para “Verdadeiro”.
• Para calcular a porcentagem de cidades com postos, você precisa saber o número total
de cidades. Você pode usar a ferramenta GetCount para obter um total sem escrever um
loop. Cuidado, você pode ter que mexer com a saída um pouco para obtê-la em um
formato que você possa usar. Veja o exemplo na documentação da ESRI que converte
o resultado GetCount em um inteiro.
Exercício 2
Na sua pasta de dados, você tem um geodatabase BD2.gdb que é uma cópia do
BD.gdb
O objetivo
No Exercício 2, sua tarefa é descobrir quais cidades têm pelo menos cinco postos
fluviométricos dentro de seus limites.
• Marque o campo "estFlu" como "Verdadeiro" para todas as cidades que tenham pelo
menos cinco postos dentro de seus limites.
• Calcule a porcentagem de cidades que têm pelo menos cinco postos dentro de seus
limites e imprima isso para o usuário.
Dicas
Esta simples modificação nos requisitos é uma mudança no jogo. A seguir indicamos
uma maneira de abordar a tarefa. Observe que é muito diferente do que você fez no
Exercício 1:
• Crie um cursor de atualização para as cidades e inicie um loop que examinará cada
cidade.
• Faça uma camada de feições com todos postos fluviométricos.
• Crie uma camada de feição apenas para a cidade atual. Você terá que fazer uma
expressão de consulta SQL para fazer isso. Lembre-se de que um UpdateCursor pode
obter valores, portanto, você pode usá-lo para obter o código da cidade atual.
109
• Utilize como identificador único para as cidades o Geocódigo do IBGE, que está
armazenado na tabela de atributos no campo “GEOCODIGO” Deve-se ter especial
atenção neste ponto, já que este código está armazenado como um valor do tipo Double,
sendo necessário realizar as conversões para valor inteiro e depois para string (texto) na
construção da expressão SQL.
• Use a função SelectLayerByLocation para encontrar todo o posto CONTAINED_BY da
cidade atual. Seu resultado será uma camada de feições de postos reduzida. Isso é
diferente do exercício 1, onde você reduziu a camada de feição das cidades.
• Uma abordagem para determinar se há pelo menos dois postos é executar a ferramenta
GetCount para descobrir quantas feições foram selecionadas e, em seguida, verificar se
o resultado é 5 ou superior. Outra abordagem é criar um cursor de pesquisa para os
postos selecionados e ver se você pode contar pelo menos cinco avanços de cursor.
• Certifique-se de excluir suas camadas de feições antes de passar para a próxima cidade.
Por exemplo: arcpy.Delete_management ("postosLayer")
• Mantenha uma contagem para cada linha marcada como "Verdadeira" e encontre a soma
como você fez no Exercício 1.
Exercício 3
Este exercício prático usa os mesmos dados iniciais do Exercício 1. Ele é projetado
para oferecer a você a prática de extrair dados com base em uma consulta de atributo.
O objetivo
Selecionar todos os postos fluviométricos que estejam em operação e coloque-os em
sua própria classe de feições. A informação se o posto está em operação é armazenada no
campo "Operando" e o valor de interesse é “Sim”.
Dicas
Use a ferramenta MakeFeatureLayer para executar a seleção. Você irá configurar uma
expressão SQL e passá-la como o terceiro parâmetro para esta ferramenta.
Depois de fazer a seleção, use a ferramenta Copy Features para criar a nova classe
de feições. Você pode passar uma camada de feição diretamente para a ferramenta Copy
Features e criar uma nova classe de feições a partir de todos as feições da seleção.
http://desktop.arcgis.com/en/arcmap/latest/tools/data-management-toolbox/copy-
features.htm
Lembre-se de excluir suas camadas de feição quando terminar.
Exercício 4
Este exercício prático requer a aplicação de uma seleção de atributos e de uma seleção
espacial. É diretamente aplicável ao Projeto 3 de várias maneiras. Os dados são os mesmos
que você usou nos exercícios 1 e 3.
O objetivo
Escreva um script que selecione todos os postos fluviométricos em uma determinada
cidade e salve-os em uma nova classe de feições. Você pode testar com a cidade de
“Linhares”.
110
Dicas
Comece criando uma camada de feições da classe de feições Cidades que contém
apenas a cidade em questão. Em seguida, você precisará criar uma camada de feições a
partir da classe de feições de postos e executar uma seleção espacial usando a operação
"CONTAINED_BY". Em seguida, use a ferramenta CopyFeatures, como no exercício
anterior, para mover as feições selecionadas para sua própria classe de feições.
Neste projeto, você usará suas novas habilidades trabalhando com seleções e cursores
para processar alguns dados de um formato "bruto" em um conjunto de dados mais
especializado para uma finalidade de mapeamento específica.
Neste exercício, suponha que você seja um analista de dados espaciais de um
departamento ambiental estadual, o gerente geral da equipe pediu que você separasse
todos as pequenas centrais hidrelétricas (PCH) que estão por passarem por análise pelo
departamento. Foi-lhe repassado um shapefile de pontos de PCHs espalhadas por todo o
território nacional, e infelizmente a informação do estado não é incluído como um dos
atributos. Você tem um segundo shapefile dos limites da divisão política estadual.
Tarefa
Escreva um script que crie shapefiles separados para cada um dos dois estágios de
PCHs que ainda precisam ser analisadas, dentro do limite do estado de MG. Escreva esse
script para que o usuário possa alterar o estado ou a lista de PCHs simplesmente editando
algumas linhas de código na parte superior do script.
Ao navegar na tabela de atributos, você notará que os valores de potência estão
armazenados como string e em KW e a área de drenagem em Km². Como parte dessa tarefa
de seleção, para simplificar as comparações com relatórios escritos usando outras unidades,
você também deve adicionar dois novos campos à tabela de atributos - somente aos novos
shapefiles, não ao shp original, para armazenar a potência em MW e a área de drenagem
em hectares.
Seu resultado deve ser algo como isto, se visto no ArcMap:
111
Exemplo de saída do Projeto 3, visualizado no ArcMap
Você não precisa criar uma ferramenta de script ArcToolbox para essa atribuição; você
pode codificar diretamente no script os parâmetros iniciais. No entanto, coloque todos os
parâmetros no topo para que possam ser facilmente manipulados por quem quiser testar o
script. Criar a ferramenta para o ArcToolbox será considerado um plus.
Notas sobre os dados
Os conjuntos de dados para o projeto estão no diretório C:\SEA5923\Dados e são so
shapefiles Estados.shp e PCH.shp.
Dê uma olhada no ArcMap nos conjuntos de dados fornecidos, particularmente nas
tabelas de atributos. O shapefile PCH contém um campo chamado "ESTAGIO" que fornece
os valores que você precisa examinar para selecionar as PCHs que ainda precisam passar
por análise (Construção, Inventariado, Operação, Outorga, PB Aprovado, PB com Aceite,
PB com Registro). Como mencionado, você foi solicitado a extrair as PCH cujo estágio ainda
estão por serem analisados para os novos shapefiles (cujos valores para o campo ESTAGIO
sejam: “Inventariado” e “”PB com Registro”), mas você precisa escrever um script que seja
capaz de lidar com outras combinação de estágios também. Existem outros campos que
112
oferecem potencial para consultas interessantes também, se você estiver procurando por
ideias além dessas.
O shapefile Estados tem um campo chamado "UF". Você pode fazer uma seleção de
atributos neste campo para selecionar “MG”, e depois seguir com uma seleção espacial para
pegar todos as PCHs que se encaixam neste estado. Por fim, reduza seus dados
selecionando apenas as PCHs para apenas as que satisfaçam as condições desejadas.
Dicas
Depois de selecionar as PCHs para o estado de MG e nos estágios desejados, use a
ferramenta Copy Feature para salvar as feições selecionadas em uma nova classe de
feições, da mesma forma que nos exercícios anteriores.
Execute neste projeto um passo de cada vez. É provavelmente mais fácil atacar
primeiro a porção de extração dos novos shapefile. Depois de criar os novos shapefiles,
percorra-os um por um, use a ferramenta "Add Field" para adicionar os campos "Pot_MW" e
"ADREN_Ha", seguido por um UpdateCursor para percorrer todas as linhas e preencher
esses novos campos com os valores apropriados.
Pode ser mais fácil fazer com que todo o processo funcione com uma única posição e,
em seguida, adicionar o loop para todas as posições depois de finalizar todas as outras
lógicas de script.
O campo de potência no shapefile original é do tipo Texto para permitir os caracteres
"KW". O método slice (fatiamento de sequência de caracteres) ou replace para tratar strings
abordados anteriormente no curso podem ser usados para separar o valor de potência
desejado e depois convertê-lo em inteiro.
Você pode completar este exercício em cerca de 50 linhas de código (incluindo espaço
em branco e comentários). Se seu código ficar muito mais longo do que isso, provavelmente
você está descartando uma maneira mais fácil.
113
Etapa 4: Python Prático para o Analista de SIG
A etapa 4 contém uma variedade de assuntos para ajudá-lo a usar o Python mais
efetivamente como um analista de SIG. As seções desta lição reforçarão o que você já
aprendeu, ao introduzir alguns novos conceitos que ajudarão a levar sua automação ao
próximo nível.
Você aprenderá agora a modularizar uma seção de código para torná-lo utilizável em
vários outros códigos. Você aprenderá como usar novos módulos do Python, como o sistema
operacional, para abrir e ler arquivos; Em seguida, você transferirá as informações desses
arquivos para conjuntos de dados geográficos que podem ser lidos pelo ArcGIS. Finalmente,
você aprenderá a usar seu sistema operacional para executar automaticamente scripts
Python a qualquer momento.
Objetivos da etapa 4
No final desta etapa, você deve:
• Entender como criar e usar funções e módulos
• Ser capaz de ler e analisar arquivos texto em Python (por exemplo, usando o módulo
csv)
• Ser capaz de criar novas geometrias e inseri-las em classes de feições usando cursores
de inserção
• Entender como automatizar tarefas com o agendamento de tarefas e arquivos em lote
• Conheçer as noções básicas de como lidar com documentos de mapas em arcpy
• Entender os dicionários de dados em Python
• Ser capaz de escrever scripts ArcGIS que criem novas feições e classes de feições, por
exemplo, a partir de informações em arquivos de texto
Funções e módulos
Um dos fundamentos de programação que nós não cobrimos anteriormente são as
funções. Para começar esta etapa, falaremos sobre funções e como você pode usá-las em
seu benefício à medida que começar a escrever scripts mais longos.
Uma função contém uma funcionalidade específica e código pode ser reutilizável. A
ideia é que você escreva a função uma vez e então possa chamá-la, durante todo o seu
script sempre que precisar. Você pode colocar um grupo de funções relacionadas em um
módulo para usá-las em vários scripts diferentes. Quando usadas apropriadamente, as
funções eliminam a repetição de código e tornam o corpo principal do script mais curto e
legível.
Funções existem em muitas linguagens de programação, e cada uma tem sua maneira
de definir uma função. No Python, você define uma função usando a instrução def. Cada
linha na função que segue o def é recuada. Aqui está uma função simples que lê o raio de
114
um círculo e informa a área aproximada do círculo. (Lembre-se que a área é igual a pi
[3.14159 ...] multiplicada pelo quadrado [** 2] do raio.)
>>> def findArea (raio):
... area = 3.14159 * raio**2
... return area
...
>>> findArea (3)
28.27431
Observe no exemplo acima que funções podem receber parâmetros ou argumentos.
Quando você chama a função acima, você fornece o raio do círculo entre parênteses. A
função retorna a área (observe a declaração de return, que é nova para você).
Assim, para encontrar a área de um círculo com um raio de 3, você poderia fazer a
função chamar findArea (3) e obter o valor de retorno 28.27431, na unidade do argumento
que foi repassado.
É comum atribuir o valor retornado a uma variável e usá-lo posteriormente em seu
código. Por exemplo, você poderia adicionar essas linhas na Janela Interativa:
>>> areaCirculo = findArea(4)
>>> print (areaCirculo)
50.26544
Para ver mais de perto o que acontece quando a função findArea(.) é chamada e
executada neste exemplo usando o recurso de visualização de execução de código do
pythontutor.com (use o link abaixo). Na janela do navegador que se abre, você verá o código
no canto superior esquerdo. Clicar nos botões "Avançar" e "Voltar" permite percorrer o
código, enquanto visualiza o que o Python armazena na memória a qualquer momento na
janela no canto superior direito.
http://pythontutor.com/visualize.html#code=def%20findArea%28radius%29%3A%0A%
20%09area%20%3D%203.14159%20*%20radius%20**%202%0A%20%09return%20area
%0A%20%09%0AaLargerCircle%20%3D%20findArea%284%29%0Aprint%20aLargerCircl
e&cumulative=false&curInstr=0&heapPrimitives=false&mode=display&origin=opt-
frontend.js&py=2&rawInputLstJSON=%5B%5D&textReferences=false
• Depois de clicar no botão "Avançar" pela primeira vez, a definição da função é lida e um
objeto de função é criado e é globalmente acessível sob o nome findArea.
• Na próxima etapa, a chamada de findArea(4) na linha 5 é executada. Isso resulta em
uma nova variável com o nome do único parâmetro da função, então radius, sendo criado
e atribuído o valor 4. Essa variável é uma variável local que só é acessível a partir do
código dentro do corpo da função.
• Em seguida, a execução do programa salta para o código de definição da função,
começando na linha 1.
• Na etapa 5, a linha 2 é executada e outra variável local com nome area de é criada e
atribuída o resultado do cálculo na linha 2 usando o valor atual do raio da variável local,
que é 4.
• Na próxima etapa, a instrução de retorno na linha 3 define o valor de retorno da função
para o valor atual variável area (50.2654).
• Ao pressionar "Avançar" novamente, a execução do programa volta para a linha 5 de
onde a função foi chamada. Como agora estamos deixando a execução do corpo da
função, todas as variáveis locais da função (raio e area) são descartadas. O valor de
115
retorno é usado no lugar da chamada de função na linha 5, neste caso significando que
é atribuído a uma nova variável global chamada areaCirculo que aparece agora na
memória.
• Na etapa final, o valor atribuído a essa variável (50.2654) é impresso.
116
de uma projeção para outra ou criar um polígono a partir de uma lista de coordenadas. Essas
funções são candidatas perfeitas para módulos. Se você quiser melhorar seu código, poderá
fazer a alteração uma vez no módulo, em vez de localizar cada script no qual duplicou o
código.
Criando um módulo
Para criar um módulo, crie um novo script no PythonWin e salve-o com a extensão .py
padrão; mas, em vez de escrever a lógica de script do início ao fim, basta escrever algumas
funções. Aqui está o que um arquivo de módulo simples pode parecer. Este módulo contém
apenas uma função, que adiciona um conjunto de pontos a uma classe de feições, dada
uma lista do Python com as coordenadas dos pontos.
# Este módulo pode ser salvo como modulo1.py
# A função abaixo cria pontos a partir de uma lista de coordenadas
# Examplo de lista: [[-113,23][-120,36][-116,-2]]
def criaPontos(listaCoordenadas, featureClass):
# Importa o arcpy e cria um cursor de inserção
import arcpy
with arcpy.da.InsertCursor(featureClass, ("SHAPE@",)) as insereLinha:
# percorre cada coordenada da lista e cria o ponto
for coordenada in listaCoordenadas:
ponto = arcpy.Point(coordenada[0],coordenada[1])
isereLinha.insertRow((ponto,))
A função acima criaPontos pode ser útil em vários scripts, por isso é muito apropriado
coloca-la em um módulo. Observe que esse script precisa funcionar com cursores de
inserção e objetos de ponto, portanto, ele requer o arcpy. É permitido importar um site
package ou módulo dentro de um módulo.
Observe também que o arcpy é importado dentro da função, não no topo do módulo,
como você está acostumado a ver. Isso é feito por motivos de desempenho. Você pode
adicionar mais funções a este módulo mais tarde, que não requeiram o arcpy. Você só deve
fazer o trabalho de importar arcpy quando necessário, isto é, se uma função chamada o
requisitar.
O arcpy só está disponível dentro do escopo desta função. Se outras funções em seu
módulo fossem chamadas, o módulo arcpy não estaria disponível para essas funções. A
noção de escopo se aplica também às variáveis que você cria nessa função, como
insereLinha. O escopo pode ser ainda mais limitado por loops que você coloca em sua
função. A variável ponto é válida apenas dentro do loop for dentro desta função específica.
Se você tentar usá-la em outro lugar, ele estaria fora do escopo e indisponível.
Usando um módulo
Então, como você poderia usar o módulo acima em um script? Imagine que o módulo
acima seja salvo por conta própria como Modulo1.py. Abaixo está um exemplo de um script
separado que importa este módulo.
# Este script pode ser salvo como adiciona_pontos.py
# Importando o modulo que contém a função desejada
import Modulo1
# Define a lista de pontos e o shapefile para editar
posicoes = [[-123.9,47.0],[-118.2,34.1],[-112.7,40.2],[-63.2,-38.7]]
posicoesFeatureClass = "c:\\SEA5923\\Dados\\Meus_Pontos.shp"
# chamando a função criaPontos do módulo Modulo1
Modulo1.criaPontos(posicoes, posicoesFeatureClass)
117
O script acima é simples e fácil de ler porque você não precisa incluir toda a lógica para
criar os pontos. Isso é feito pela função createPoints no módulo que você importou,
practiceModule1. Note que para chamar uma função de um módulo, você precisa usar a
sintaxe module.function ().
Leituras
Para reforçar o material nesta seção, leia Zandbergen 12.1 - 12.5, que fala sobre a
criação de funções e módulos do Python.
Prática
Antes de seguir em frente, pratique o PythonWin tentando escrever as seguintes
funções. Essas funções não serão avaliadas, mas a experiência de escrevê-las ajudará você
no Projeto 4.
• Uma função que retorna o perímetro de um quadrado, dado o comprimento de um lado.
• Uma função que usa um caminho para uma classe de feições como parâmetro e retorna
uma lista Python dos campos da tabela de atributos dessa classe de feições. Pratique
chamando a função e imprimindo a lista. No entanto, não imprima a lista dentro da
função.
• Uma função que retorna a distância euclidiana entre quaisquer duas coordenadas. As
coordenadas podem ser fornecidas como parâmetros na forma (x1, y1, x2, y2). Por
exemplo, se suas coordenadas foram (312088, 60271) e (312606, 59468), sua chamada
de função pode ter esta aparência: distEuclidiana(312088, 60271, 312606, 59468). Use
a fórmula pitagórica A**2 + B**2 = C**2.
A melhor prática é colocar suas funções dentro de um módulo e ver se você pode
chamá-las com sucesso de um script separado. Se você tentar percorrer o código usando o
depurador, perceberá que o depurador se movimenta de um lado para o outro entre o script
e o módulo sempre que você chamar uma função no módulo.
Dicionários Python
Em programação, muitas vezes queremos armazenar grandes quantidades de dados
que de alguma forma estejam armazenados dentro de uma única variável. Na etapa 2, você
já aprendeu sobre listas, que fornecem uma opção para isso. Contanto que a memória
disponível permita, você pode armazenar quantos elementos em uma lista desejar e o
método append(.) permite adicionar mais elementos a uma lista existente.
Dicionários são outra estrutura de dados que permite armazenar informações
complexas em uma única variável. Enquanto as listas armazenam elementos em uma
sequência simples e os elementos são acessados com base em seu índice na sequência,
os elementos armazenados em um dicionário consistem em pares de valor-chave e sempre
usamos a chave para recuperar os valores correspondentes no dicionário. Funciona como
num dicionário real onde você procura informações (o valor armazenado) sob uma palavra-
chave específica (a chave).
118
Dicionários podem ser úteis para realizar um mapeamento, por exemplo, de palavras
inglesas para as palavras correspondentes em espanhol. Aqui está como você pode criar
um dicionário para apenas os números de um a quatro:
>>> englishToSpanishDic = {"one": "uno", "two": "dos", "three": "tres",
"four": "cuatro"}
As chaves {} delimitam o dicionário de forma semelhante como os colchetes [] fazem
para listas. Dentro do dicionário, temos quatro pares de valores-chave separados por
vírgulas. A chave e o valor de cada par são separados por dois pontos. A chave aparece à
esquerda, enquanto o valor armazenado sob a chave aparece no lado direito.
Agora podemos usar o dicionário armazenado na variável englishToSpanishDic para
procurar a palavra em espanhol para um número em inglês, por exemplo
>>> print (englishToSpanishDic["two"])
dos
Para recuperar algum valor armazenado no dicionário, usamos o nome da variável
seguido de colchetes contendo a chave sob a qual o valor é armazenado no dicionário.
Se usarmos a mesma notação, mas no lado esquerdo de um operador de atribuição
(=), adicionarmos um novo valor para uma nova chave adicionamos o novo par ao dicionário
existente:
>>> englishToSpanishDic["five"] = "cinco"
>>> print (englishToSpanishDic)
{"four": "cuatro", "three": "tres", "five": "cinco", "two": "dos", "one":
"uno"}
Aqui adicionamos o valor "cinco" para a chave “five”. Se algo já tivesse sido
armazenado sob a chave "five" no dicionário, o novo valor adicionado seria sobrescrito. Você
deve ter notado que a ordem dos elementos do dicionário na saída mudou, mas isso não
importa, já que sempre acessamos os elementos em um dicionário por meio da chave. Se o
nosso dicionário contivesse muito mais pares de palavras, poderíamos usá-lo para criar um
tradutor muito primitivo que passasse um texto em inglês palavra por palavra e substituísse
cada palavra pela palavra espanhola correspondente recuperada do dicionário.
Evidentemente, usar essa abordagem simples provavelmente resultaria em traduções
bastante hilárias.
Agora vamos usar dicionários Python para fazer algo um pouco mais complexo. Vamos
simular o processo de criação de um índice de livros que lista os números de página em que
determinadas palavras-chave ocorrem. Queremos começar com um dicionário vazio e
depois percorrer o livro página por página. Sempre que encontramos uma palavra que
consideramos importante o suficiente para ser listada no índice, nós a adicionamos junto ao
número da página no dicionário.
Para criar um dicionário vazio em uma variável chamada indiceLivro, usamos a notação
com as chaves, mas nada entre elas:
>>> indiceLivro = {}
>>> print (indiceLivro)
{}
Agora digamos que a primeira palavra-chave que encontramos no livro de
programação imaginária que estamos passando é a palavra "função" na página 2. Agora
queremos armazenar o número da página 2 (valor) sob a palavra-chave "função" (chave) no
dicionário. Mas como as palavras-chave podem aparecer em muitas páginas, o que
119
queremos armazenar como valores no dicionário não são números individuais, mas listas de
números de páginas. Portanto, o que colocamos em nosso dicionário é uma lista com o
número 2 como seu único elemento:
>>> indiceLivro["função"] = [2]
>>> print (indiceLivro)
{"função": [2]}
Em seguida, encontramos a palavra-chave "módulo" na página 3. Por isso,
adicionamos ao dicionário da mesma maneira:
>>> indiceLivro["módulo"] = [3]
>>> print (indiceLivro)
{"função": [2], "módulo": [3]}
Então, agora, nosso dicionário contém dois pares de valores-chave e, para cada chave,
armazena uma lista com apenas um único número de página. Digamos que em seguida
encontremos a palavra-chave “função” uma segunda vez, desta vez na página 5. Nosso
código para adicionar o número de página adicional à lista armazenada sob a “função” chave
agora precisa ser um pouco diferente porque já temos algo armazenado para ele no
dicionário e não queremos sobrescrever essa informação. Em vez disso, recuperamos a lista
atualmente armazenada de números de página e adicionamos o novo número a ela com o
método append( ):
>>> paginas = indiceLivro["função"]
>>> paginas.append(5)
>>> print (indiceLivro)
{"função": [2, 5], "módulo": [3]}
>>> print (indiceLivro["função"])
[2, 5]
Note que nós não temos que colocar a lista de números de páginas armazenados na
variáveis paginas ao dicionário depois de adicionar o novo número de página. Tanto a
variável paginas quanto o dicionário se referem à mesma lista, de forma que o acréscimo do
número altera ambos. Nosso dicionário agora temos uma lista de dois números de página
para a chave “função” e ainda uma lista com apenas um número de página para a chave
“módulo”. Certamente você pode imaginar como construiríamos um dicionário enorme para
o livro inteiro, continuando esse processo. Os dicionários podem ser usados em conjunto
com um loop for para percorrer as chaves dos elementos no dicionário. Isso pode ser usado
para imprimir o conteúdo de um dicionário inteiro:
>>> for k in indiceLivro: # loop através das chaves do dicionário
... print ("Chave:" + k) # imprime a chave
... print ("Páginas:" + str(indiceLivro[k])) # imprime o valor
Chave: função
Páginas: [2, 5]
Chave: módulo
páginas: [3]
Ao adicionar o segundo número de página para “função”, nós decidimos que isso
precisa ser tratado de maneira diferente do que quando adicionamos o primeiro número de
página. Mas como isso poderia ser realizado no código? Podemos verificar se algo já está
armazenado em uma chave em um dicionário usando uma instrução if junto com o operador
"in":
>>> Chave = "função"
>>> if Chave in indiceLivro:
120
... print("entrada existe")
... else:
... print("entrada não existe")
...
entrada existe
Portanto, supondo que tenhamos a palavra-chave atual armazenada na variável
“palavra” e o número da página correspondente armazenado na variável “paginaNr”, a parte
seguinte do código decidirá por si só como adicionar o novo número da página ao dicionário:
palavra = "módulo"
paginaNr = 7
if palavra in indiceLivro:
# entrada para palavra existe, então apenas adicionamos a página
paginas = indiceLivro[palavra]
paginas.append(paginaNr)
else:
# não existe entrada para palavra, então adicionamos nova entrada
indiceLivro[palavra] = [paginaNr]
Uma versão mais sofisticada desse código também verificaria se a lista de números de
páginas recuperados no bloco if já contém o novo número de página para lidar com o caso
de uma palavra-chave ocorrer mais de uma vez na mesma página. Sinta-se à vontade para
pensar em como isso poderia ser incluído.
Leituras
Leia a seção 6.8 de Zandbergen para mais informações e exemplos usando dicionários
Python.
121
Existem várias abordagens diferentes para análise. Normalmente, o mais sábio é
verificar se existe algum módulo Python que examine o texto para você e o transforme em
um objeto com o qual você possa trabalhar. Nesta etapa, trabalharemos com o módulo "csv"
do Python que pode ler valores delimitados por vírgulas e transformá-los em uma lista do
Python. Outras bibliotecas úteis como essa incluem lxml e xml.dom para analisar XML e
BeautifulSoup para analisar HTML.
Se não existir um módulo ou biblioteca que atenda às suas necessidades de análise,
você terá que extrair as informações do texto usando os métodos de manipulação de strings
do Python. Um dos mais úteis é o string.split(), que transforma uma string grande em uma
lista de strings menores com base em algum caractere delimitador, como espaço ou vírgula.
No entanto, quando você escreve seu próprio código, é difícil antecipar todos os casos
excepcionais que você pode encontrar. Por exemplo, às vezes, um arquivo de valor
separado por vírgula pode ter subsequências que contêm naturalmente vírgulas, como datas
ou endereços. Nestes casos não é suficiente dividir a string usando uma simples vírgula
como delimitador e você precisa adicionar lógica extra ao código.
Outra armadilha na análise é o uso de "números mágicos" para delimitar um número
específico de caracteres em uma string ou para se referir a um número de coluna específico
em uma planilha. Se a estrutura dos dados for alterada, ou se o script for aplicado a dados
com uma estrutura ligeiramente diferente, o código poderá ficar inoperável e exigiria uma
correção cirúrgica de precisão. As pessoas que leem seu código e veem um número
diferente de 0 (para começar uma série) ou 1 (para incrementar um contador) muitas vezes
ficam imaginando como o número foi derivado e a que se refere. Na programação, números
diferentes de 0 ou 1 são números mágicos que normalmente devem ser evitados, ou pelo
menos acompanhados por um comentário explicando a que o número se refere.
Há um número infinito de cenários de análise que você pode encontrar. Esta lição
tentará ensinar-lhe uma abordagem geral percorrendo apenas um módulo e exemplo.
O módulo csv do Python
Um formato de intercâmbio de dados baseado em texto comum é o arquivo de valores
separados por vírgula (CSV). Isso costuma ser usado ao transferir planilhas ou outros dados
tabulares. Cada linha no arquivo representa uma linha do conjunto de dados e as colunas
nos dados são separadas por vírgulas. O arquivo geralmente começa com uma linha de
cabeçalho contendo todos os nomes de campo.
Programas de planilhas como o Microsoft Excel podem entender a estrutura CSV e
exibir todos os valores em uma grade de linha de coluna. Um arquivo CSV pode parecer um
pouco mais confuso quando você o abre em um editor de texto, mas pode ser útil sempre
pensar nele como uma estrutura de grade. Se você tivesse uma lista de linhas do Python e
uma lista de valores de colunas do Python para cada linha, você poderia usar a lógica de
loop para extrair qualquer valor que precisasse. Isso é exatamente o que o módulo csv do
Python oferece.
É mais fácil aprender sobre o módulo csv observando um exemplo real. O cenário
abaixo mostra como o módulo csv pode ser usado para analisar informações de um arquivo
de rastreamento GPS.
Apresentando o exemplo de análise de rastreamento GPS
Este exemplo lê um arquivo de texto coletado de uma unidade GPS. As linhas no
arquivo representam as leituras obtidas da unidade GPS à medida que o usuário percorreu
um caminho. Nesta seção da lição, você aprenderá uma maneira de analisar as coordenadas
122
de cada leitura. A próxima seção da lição usa uma variação deste exemplo para mostrar
como você pode gravar a trilha do usuário em uma classe de feições de polilinhas.
O arquivo para este exemplo é chamado gps_track.txt e está armazenado na pasta de
dados, ele se parece com a sequência de texto mostrada abaixo. (Observe que as quebras
de linha foram adicionadas ao arquivo mostrado abaixo e o tamanho da fonte diminuido para
garantir que o texto fique dentro das margens da página.
type,ident,lat,long,y_proj,x_proj,new_seg,display,color,altitude,depth,temp,time,
model,filename,ltime
TRACK,ACTIVE LOG,40.78966141,-77.85948515,4627251.76270444,1779451.21349775,True,
False,255,358.228393554688,0,0,2008/06/11-14:08:30,eTrex Venture, ,2008/06/11 09:08:30
TRACK,ACTIVE LOG,40.78963995,-77.85954952,4627248.40489401,1779446.18060893,False,
False,255,358.228393554688,0,0,2008/06/11-14:09:43,eTrex Venture, ,2008/06/11 09:09:43
TRACK,ACTIVE LOG,40.78961849,-77.85957098,4627245.69008772,1779444.78476531,False,
False,255,357.747802734375,0,0,2008/06/11-14:09:44,eTrex Venture, ,2008/06/11 09:09:44
etc. ...
Observe que o arquivo começa com uma linha de cabeçalho, explicando o significado
dos valores contidos nas leituras da unidade GPS. Cada linha subsequente contém uma
leitura. O objetivo deste exemplo é criar uma lista do Python contendo as coordenadas X, Y
de cada leitura. Especificamente, o script deve ser capaz de ler o arquivo acima e imprimir
uma sequência de texto como a mostrada abaixo.
[['-77.85948515', '40 .78966141 '], [' -77.85954952 ', '40 .78963995'],
['-77.85957098', '40 .78961849 '], etc.]
Abordagem para analisar a trilha do GPS
Antes de começar a analisar um arquivo, é útil descrever o que você vai fazer e dividir
a tarefa em partes gerenciáveis. Aqui está um algoritmo para a abordagem que vamos dar
neste exemplo:
• Abra o arquivo.
• Leia a linha de cabeçalho.
• Faça um loop pela linha de cabeçalho para encontrar as posições de índice dos valores
"lat" e "long".
• Leia o resto das linhas, uma por uma.
• Encontre os valores na lista que correspondem às coordenadas lat e long e grave-os em
uma nova lista.
Importando o módulo
Quando você trabalha com o módulo csv, é necessário importá-lo explicitamente na
parte superior do script, assim como faz com o arcpy.
importar csv
Você não precisa instalar nada especial para obter o módulo csv; apenas vem com a
instalação básica do Python.
Abrindo o arquivo e criando o leitor CSV
A primeira coisa que o script precisa fazer é abrir o arquivo. O Python contém um
método open() integrado para fazer isso. Os parâmetros para este método são o caminho
para o arquivo e o modo no qual você deseja abrir o arquivo (ler, escrever, etc.). Neste
exemplo, "r" significa o modo somente leitura. Se você quisesse escrever itens no arquivo,
usaria "w" como o modo.
123
gpsTrack = open("C:\\SEA5923\\Dados\\gps_track.txt", "r")
Observe que seu arquivo não precisa ter a extensão .csv para ser lido pelo módulo
CSV. Pode ter a extensão .txt desde que o texto no arquivo esteja de acordo com o padrão
CSV, no qual as vírgulas separam as colunas e um parágrafo separando as linhas. Depois
que o arquivo é aberto, você cria um objeto de leitura CSV, dessa maneira:
leitorCSV = csv.reader(gpsTrack)
Este objeto é como um cursor. Você pode usar o método next() para ir para a próxima
linha, e também pode usá-lo com um loop for para iterar todas as linhas do arquivo.
Lendo a linha de cabeçalho
A linha de cabeçalho de um arquivo CSV é diferente das outras linhas. Você recebe as
informações sobre todos os nomes de campo. Portanto, você examinará essa linha um
pouco diferente das outras linhas. Primeiro, você avança o leitor CSV para a linha de
cabeçalho usando o método next(), assim:
cabecalho = leitorCSV.next()
Isso retorna uma lista do Python com cada item no cabeçalho. Lembre-se que o
cabeçalho era uma string longa, começando com: "type, ident, lat, long ...". O leitor CSV
divide o cabeçalho em uma lista de partes que podem ser referenciadas por um número de
índice. O delimitador padrão, ou caractere de separação, para essas partes é a vírgula.
Portanto, o cabecalho[0] teria o valor "type", cabecalho[1] teria o valor "ident" e assim por
diante.
Estamos mais interessados em extrair os valores de latitude e longitude desse arquivo,
portanto, teremos que armazenar a posição das colunas "lat" e "long" neste arquivo. Usando
a lógica acima, você usaria o cabecalho[2] para obter "lat" e cabecalho[3] para obter "long".
No entanto, e se você obtivesse algum outro arquivo em que esses nomes de campos
estivessem todos em uma ordem diferente? Você não poderia ter certeza de que a coluna
com índice 2 representava "lat" e assim por diante.
Uma maneira mais segura de analisar é usar o método list.index() e pedir à lista que
lhe forneça a posição de índice correspondente a um nome de campo específico, assim:
indiceLat = cabecalho.index ("lat")
indiceLong = cabecalho.index ("long")
Em nosso caso, indiceLat teria um valor de 2 e indiceLong teria um valor de 3, mas
nosso código agora é flexível o suficiente para lidar com essas colunas em outras posições.
Processando o restante das linhas no arquivo
O resto do arquivo pode ser lido usando um loop. Nesse caso, você trata o leitorCSV
como uma lista iterável das linhas restantes no arquivo. Cada execução do loop leva uma
linha e a divide em uma lista de valores do Python. Se obtivermos o valor com o índice 2
(representado pela variável indiceLat), então temos a latitude. Se obtivermos o valor com o
índice 3 (representado pela variável indiceLong), obteremos a longitude. Assim que
obtivermos esses valores, podemos adicioná-los a uma lista que criamos, chamada
listaCoord:
# Crie uma lista vazia
listaCoord = []
124
lat = linha[indiceLat]
lon = linha[indiceLong]
listaCoord.append ([lat, lon])
125
Resumo
Analisar qualquer parte do texto requer que você esteja familiarizado com os métodos
de abertura e leitura de arquivos, a estrutura do texto que você vai analisar, os módulos de
análise disponíveis que se ajustam à sua estrutura de texto e os métodos de manipulação
de string. No exemplo anterior, analisamos um arquivo de texto simples, extraindo
coordenadas coletadas por uma unidade GPS portátil. Usamos o módulo csv para dividir
cada leitura de GPS e encontrar os valores de latitude e longitude. Na próxima seção da
lição, você aprenderá como poderia fazer mais com essas informações, escrevendo as
coordenadas em um conjunto de dados de polilinhas.
Ao usar o Python no seu trabalho SIG, você pode encontrar uma variedade de tarefas
de análise. Ao abordá-los, não tenha medo de procurar ajuda de exemplos da Internet,
tópicos de referência de código, como os relacionados nesta lição.
Leituras
Vale a pena ler o capítulo de Zandbergen 7.6, que fala sobre a análise de arquivos de
texto. Qualquer exemplo que você possa ter com a análise de texto ajudará você quando
encontrar um novo arquivo que precisa ler. Você terá essa experiência nos exercícios
práticos e nos projetos desta etapa.
126
# Crie uma nova matriz vazio
matriz = arcpy.Array ()
# Crie alguns pontos
ponto1 = arcpy.Point(-121.34,47.1)
ponto2 = arcpy.Point(-121.29,47.32)
ponto3 = arcpy.Point(-121.31,47.02)
# Coloque os pontos na matriz
array.add(ponto1)
array.add(ponto2)
array.add(ponto3)
# Crie uma polilinha a partir da matrizagora completo
polilinha = arcpy.Polyline (matriz, referenciaEspacial)
Naturalmente, você normalmente não criará pontos manualmente em seu código como
este com coordenadas inseridas no próprio script. É mais provável que você analise as
coordenadas de um arquivo ou capture-as de alguma fonte externa, como uma série de
cliques do mouse na tela.
Criando uma polilinha a partir de um arquivo de GPS
Veja como você pode analisar as coordenadas de um arquivo de texto criado por GPS,
como o da seção anterior da lição. Este código lê todos os pontos capturados pelo GPS e
os adiciona a uma polilinha. Em seguida, a polilinha é gravada em um arquivo shapefile vazio
e pré-existente com um sistema de coordenadas geográficas chamado tracklines.shp. Se
você não tem um shapefile no disco, pode usar a ferramenta Create Feature Class para criar
um no seu script.
# Este script lê um arquivo GPS track em formato CSV e
# e cria polilinhas a partir dos pares de coordenadas
import csv
import arcpy
# Definindo as variáveis de entrada e saída
gpsTrack = open("C:\\SEA5923\\Dados\\gps_track.txt", "r")
polilinhaFC = " C:\\SEA5923\\Dados\\tracklines.shp"
referenciaEspacial = arcpy.Describe(polilinhaFC).spatialReference
# Definindo o objeto leitor CSV e processando o cabeçalho
leitorCSV = csv.reader(gpsTrack)
cabecalho = leitorCSV.next()
indiceLat = cabecalho.index("lat")
indiceLong = cabecalho.index("long")
# Criando uma matriz vazia
matrizVertices = arcpy.Array()
# Percorrendo as linhas do arquivo e armazenando as coordenadas
for linha in leitorCSV:
lat = linha[indiceLat]
lon = linha[indiceLong]
# Criando o ponto a partir das coordenadas adicionando-os à matriz
vertice = arcpy.Point(lon,lat)
matrizVertices.add(vertice)
127
O script acima começa como o da seção anterior da lição. Primeiro, analisa a linha de
cabeçalho do arquivo para determinar o índice das coordenadas de latitude e longitude em
cada leitura. Mas, observe que uma matriz é criada para conter os pontos da polilinha:
matrizVertice = arcpy.Array()
Depois disso, é iniciado um loop que lê cada linha e cria um objeto de ponto a partir
dos valores de latitude e longitude. No final do loop, o ponto é adicionado à matriz.
for linha in leitorCSV:
lat = linha[indiceLat]
lon = linha[indiceLong]
# Criando o ponto a partir das coordenadas adicionando-os à matriz
vertice = arcpy.Point(lon, lat)
matrizVertice.add(vertice)
Uma vez que todas as linhas tenham sido lidas, o loop sai e um cursor de inserção é
criado usando "SHAPE@" como o único elemento na tupla dos campos afetados. Em
seguida, um objeto Polyline é criado e usado como o primeiro (e único) elemento da tupla
para o método insertRow():
# Criando um cursor de inserção
with arcpy.da.InsertCursor (polylineFC, ("SHAPE @",)) como cursor:
# Coloque o array em uma polilinha e escreva-o na classe de recurso
polyline = arcpy.Polyline (vertexArray, spatialRef)
cursor.insertRow ((polyline,))
Lembre-se de que o cursor coloca um bloqueio em seu conjunto de dados, portanto,
esse script não cria o cursor até que seja absolutamente necessário (em outras palavras,
após o loop).
Estendendo o exemplo para várias polilinhas
Suponha que seu GPS permita marcar o início e a parada de diferentes faixas. Como
você lidaria com isso no código? Você pode usar um arquivo de texto modificado com várias
faixas se quiser experimentar o seguinte exemplo.
C:\\SEA5923\\Dados\\gps_track_modificado.txt"
Observe que no arquivo de texto do GPS, há uma coluna denominada new_seg:
type,ident,lat,long,y_proj,x_proj,new_seg,display,color,altitude,depth,
temp,time,model,filename,ltime
new_seg é uma propriedade booleana que determina se a leitura começa uma nova
faixa. Se new_seg = True, você precisará gravar a polilinha existente no shapefile e começar
a criar uma nova. Observe atentamente este exemplo de código e observe como ele difere
do anterior para lidar com várias polilinhas:
# Este script lê um arquivo GPS track em formato CSV e
# e cria polilinhas a partir dos pares de coordenadas
# versão para múltiplas linhas
128
import csv
import arcpy
# Definindo as variáveis de entrada e saída
gpsTrack = open("C:\\SEA5923\\Dados\\gps_track_modificado.txt", "r")
polilinhaFC = "C:\\SEA5923\\Dados\\tracklines_ml.shp"
referenciaEspacial = arcpy.Describe(polilinhaFC).spatialReference
# Definindo o objeto leitor CSV e processando o cabeçalho
leitorCSV = csv.reader(gpsTrack)
cabecalho = leitorCSV.next()
indiceLat = cabecalho.index("lat")
indiceLong = cabecalho.index("long")
novoIndice = cabecalho.index("new_seg")
# Escrevendo a matriz numa feature class como uma polilinha
with arcpy.da.InsertCursor(polilinhaFC, ("SHAPE@",)) as cursor:
# Criando uma matriz vazia
matrizVertices = arcpy.Array()
# Percorrendo as linhas do arquivo e armazenando as coordenadas
for linha in leitorCSV:
novo = linha[novoIndice].upper()
# Se iniciar uma nova linha, adicione a linha concluída à FC
if novo == "TRUE":
if matrizVertices.count > 0:
addpolilinha(cursor, matrizVertices, referenciaEspacial)
# Pegando os valores de Lat/Long
lat = linha[indiceLat]
lon = linha[indiceLong]
# Cria o ponto a partir das coordenadas adiciona-o à matriz
vertice = arcpy.Point(lon,lat)
matrizVertices.add(vertice)
# Adiciona a polilinha ao shapefile
addPolilinha(cursor, matrizVertices, referenciaEspacial)
A primeira coisa que você deve notar é que esse script usa uma função. A função
addPolilinha adiciona uma polilinha a uma classe de feições, considerando três parâmetros:
(1) um cursor de inserção existente, (2) uma matriz e (3) uma referência espacial. Essa
função reduz o código repetido e torna o script mais legível.
Aqui está uma olhada na função addPolyline:
# Função para adicionar uma polilinha
def addPolilinha(cursor, matriz, sr):
polilinha = arcpy.Polyline(matriz, sr)
cursor.insertRow((polilinha,))
matriz.removeAll()
Observe que não há problema em usar o arcpy na função acima, pois ele está dentro
do corpo de um script que importa arcpy. No entanto, você deseja evitar o uso de variáveis
na função que não estão definidas dentro da função ou transmitidas como parâmetros.
A função addPolilinha é chamada duas vezes no script: uma vez dentro do loop, o que
seria de esperar, e uma vez no final para garantir que a polilinha final seja adicionada ao
shapefile. É aqui que escrever uma função reduz o código repetido.
Enquanto você lê cada linha do arquivo de texto, como você determina se começa uma
nova faixa? Primeiro de tudo, observe que adicionamos mais um valor para procurar neste
script:
novoIndice = cabecalho.index ("new_seg")
129
A variável novoIndice nos mostra qual posição no cabeçalho é ocupada pela
informação booleana new_seg que nos informa se uma nova polilinha está começando. O
que será verificado mais tarde no código:
novo = linha[novoIndice].upper()
if matrizVertices.count> 0:
addPolilinha (cursor, matrizVertices, referenciaEspacial)
O código acima verifica se há pelo menos um ponto na matriz e, em seguida, chama a
função addPolilinha, passando o cursor e a matriz.
Aqui está outra questão a considerar: Como sabemos que o objeto matriz tem uma
propriedade count que nos informa quantos itens estão nele? Isso vem do tópico de Ajuda
do ArcGIS Desktop que descreve a classe Array. Nesta seção da ajuda há tópicos
descrevendo cada classe em arcpy, e você a consutará frequentemente se você trabalhar
com geometrias do ArcGIS em Python.
No tópico Array, da ajuda, localize a tabela Propriedades e observe que a Matriz possui
uma propriedade de contagem somente leitura. Se estivéssemos trabalhando com uma lista
Python, poderíamos usar len(matrizVertices), mas no nosso caso matrizVertices é um objeto
Array que é nativo do modelo de programação de geoprocessamento do ArcGIS. Isso
significa que é um objeto especializado projetado pela ESRI, e você só pode aprender seus
métodos e propriedades examinando a documentação.
Método alternativo para criar polilinhas e polígonos
Na versão 10.6 do ArcGIS Desktop, a ESRI possibilitou a criação de objetos Polyline e
Polygon, fornecendo uma lista de pares de coordenadas, eliminando a necessidade de criar
um objeto Point para cada vértice e adicionar cada Point a um Array. Esse método alternativo
é demonstrado na documentação, embora com um conjunto de coordenadas que é atribuído
a uma lista de uma só vez. Aqui está uma versão do script anterior que usa a abordagem de
lista de coordenadas, mas constrói a lista incrementalmente:
https://desktop.arcgis.com/en/arcmap/latest/analyze/python/writing-
geometries.htm#ESRI_SECTION1_6355676F4A124BC88F825502F3C8BE45
# Este script lê um arquivo GPS track em formato CSV e
# e cria polilinhas a partir dos pares de coordenadas
# versão para múltiplas linhas
# Cria as polilinhas a partir de listas ao invés de matrizes
130
# Corpo principal do script
import csv
import arcpy
# Definindo as variáveis de entrada e saída
gpsTrack = open("C:\\SEA5923\\Dados\\gps_track_modificado.txt", "r")
polilinhaFC = "C:\\SEA5923\\Dados\\tracklines_ml.shp"
referenciaEspacial = arcpy.Describe(polilinhaFC).spatialReference
# Definindo o objeto leitor CSV e processando o cabeçalho
leitorCSV = csv.reader(gpsTrack)
cabecalho = leitorCSV.next()
indiceLat = cabecalho.index("lat")
indiceLong = cabecalho.index("long")
novoIndice = cabecalho.index("new_seg")
# Escrevendo a matriz numa feature class como uma polilinha
with arcpy.da.InsertCursor(polilinhaFC, ("SHAPE@",)) as cursor:
# Criando uma lista de vértices vazia
vertices = []
# Percorrendo as linhas do arquivo e armazenando as coordenadas
for linha in leitorCSV:
novo = linha[novoIndice].upper()
# Se iniciar uma nova linha, adicione a linha concluída à FC
if novo == "TRUE":
if len(vertices) > 0:
addPolyline(cursor, vertices, referenciaEspacial)
# Pegando os valores de Lat/Long
lat = linha[indiceLat]
lon = linha[indiceLong]
# Adiciona as coordenadas para a lista de vértices
vertices.append((lon,lat))
# Adiciona a polilinha ao shapefile
addPolilinha(cursor, vertices, referenciaEspacial)
Resumo
Você pode gravar geometrias em classes de feições do ArcGIS usando uma
combinação de objetos de geometria incluídos no ArcGIS. O fluxo de trabalho comum é criar
objetos Point, que você adiciona a um objeto Array. Você pode usar o objeto Array e uma
referência espacial para criar objetos Polyline e Polygon. Em seguida, você usa um cursor
de inserção para atribuir a geometria da matriz ao campo de geometria da classe de feições
(normalmente chamado de "SHAPE"). Um segundo fluxo de trabalho é criar Polilinhas /
Polígonos usando uma lista de pares de coordenadas.
Você pode estar se perguntando como é possível criar uma feição de várias partes
(como um estado cujo litoral contém várias ilhas) ou um polígono com um "furo". Essas
geometrias mais complexas exigem regras especiais para ordenar e aninhar Pontos e
Matrizes. Estes temas são abordados no livro de Zandbergen.
Leituras
Leia Zandbergen 8.1 - 8.6, que contém um bom resumo de como ler e escrever
geometrias da Esri.
131
Automação com arquivos em lote e tarefas agendadas
Já falamos sobre os benefícios de automatizar seu trabalho por meio de scripts Python.
É bom poder executar várias ferramentas de geoprocessamento em algumas linhas sem
usar manualmente as caixas de ferramentas no ArcMap. O que poderia ser mais
automático? Quem sabe carregar o PythonWin, abrir seu script e executá-lo? Nesta seção
da lição, levaremos a automação um passo adiante, discutindo como você pode fazer com
que seus scripts sejam executados automaticamente.
Scripts e seu sistema operacional
Na maior parte do tempo, nós executamos scripts neste curso, através do PythonWin.
Seu sistema operacional (Windows) pode executar scripts diretamente. Talvez você tenha
tentado clicar duas vezes em um arquivo .py para executar um script. Contanto que o
Windows entenda que os arquivos .py representam um script Python e que ele deve usar o
interpretador Python para executar o script, o script será iniciado imediatamente.
Quando você tenta iniciar um script automaticamente clicando duas vezes nele, é
possível receber uma mensagem dizendo que o Windows não sabe qual programa usar para
abrir seu arquivo. Se isso acontecer com você, use o botão Procurar na caixa de diálogo de
erro para procurar o executável Python, provavelmente localizado em
C:\Python27\ArcGIS10.x\Python.exe. Certifique-se de que "Usar sempre o programa
selecionado para abrir este tipo de arquivo" esteja marcado e clique em OK. O Windows
agora entende que os arquivos .py devem ser executados usando Python.
Clicar duas vezes em um arquivo .py fornece ao seu sistema operacional o comando
simples para executar esse script Python. Você pode alternativamente dizer ao seu sistema
operacional para executar um script usando a interface de linha de comando do Windows.
Este ambiente apenas fornece uma janela em branco com um cursor piscante e permite que
você digite o caminho para um script ou programa, seguido por uma lista de parâmetros. É
uma maneira limpa e minimalista de executar um script. No Windows, você pode abrir a linha
de comando digitando cmd na caixa Pesquisar.
A linha de comando
O uso avançado da linha de comando está fora do escopo deste curso. Por enquanto,
é suficiente dizer que você pode executar um script a partir da linha de comando, digitando
o caminho do executável Python, seguido pelo caminho completo para o script, desta forma:
C:\Python27\ArcGIS10.x\Python.exe C:\SEA5923\Scripts\Etapa1\Projecto1.py
Se o script receber parâmetros, você também deverá digitar cada argumento separado
por um espaço. Lembre-se de que os argumentos são os valores que você fornece para os
parâmetros do script. Aqui está um exemplo de um comando que executa um script com
dois argumentos, ambas as sequências que representam nomes de caminho. Observe que
você deve usar o regular \ em seus caminhos ao fornecer argumentos da linha de comando
(não / ou \\ como você usaria no PythonWin).
C:\Python27\ArcGIS10.x\Python.exe C:\SEA5923\Scripts\Etapa2\Projecto2.py
C:\SEA5923\Dados\ C:\SEA5923\Dados\Cidades.shp
Se o script for executado com sucesso, muitas vezes você não verá nada, exceto um
novo prompt de comando (lembre-se, isso é minimalista!). Se o seu script foi criado para
imprimir uma mensagem, você deverá ver a mensagem. Se o seu script foi criado para
132
modificar arquivos ou dados, você pode verificar esses arquivos ou dados (talvez usando o
ArcCatalog) para certificar-se de que o script foi executado corretamente.
Você também verá mensagens se seu script falhar. Às vezes, essas são as mesmas
mensagens que você veria na Janela Interativa do Python. Outras vezes, as mensagens são
mais úteis do que você veria no PythonWin, tornando a linha de comando outra ferramenta
útil para depuração. Infelizmente, algumas vezes as mensagens são menos úteis.
Arquivos em lote
Por que a linha de comando é tão importante em uma discussão sobre automação?
Afinal, ainda é preciso trabalhar para abrir a linha de comando e digitar os comandos. A
vantagens sobre os comandos é que eles também podem ser roteirizados. Você pode listar
vários comandos em um arquivo simples baseado em texto, chamado de arquivo em lotes.
Executar o arquivo em lote executa todos os comandos nele.
Aqui está um exemplo de um arquivo em lote simples que executa os dois scripts
acima. Para criar esse arquivo em lote, você pode colocar o texto abaixo em um arquivo
vazio do Bloco de Notas e salvá-lo com uma extensão .bat. Lembre-se que isso não é
Python; é a sintaxe do comando:
@ ECHO OFF
REM Executa meus scripts de projeto
C:\Python27\ArcGIS10.x\Python.exe C:\SEA5923\Scripts\Etapa1\Projecto1.py
ECHO Executando Projeto 1
C:\Python27\ArcGIS10.x\Python.exe C:\SEA5923\Scripts\Etapa2\Projecto2.py
C:\SEA5923\Dados\ C:\SEA5923\Dados\Cidades.shp
ECHO Executando Projeto 2
PAUSE
Aqui estão algumas notas sobre o arquivo de lote acima, começando do topo:
• @ECHO OFF impede que todas as linhas do seu arquivo de lote sejam impressas na
janela da linha de comando, ou no console, quando você executa o arquivo. É um
procedimento padrão para usar isso como a primeira linha do arquivo de lote, a menos
que você realmente queira ver qual linha do arquivo está sendo executada (talvez para
fins de depuração).
• O REM é como você coloca um comentário no seu arquivo de lote, da mesma forma que
# denota um comentário no Python.
• Você coloca comandos no seu arquivo de lote usando a mesma sintaxe usada na linha
de comando.
• O ECHO imprime algo no console. Isso pode ser útil para depuração, especialmente
quando você usou @ECHO OFF porque não deseja ver cada linha do arquivo em lote
impressa no console.
• PAUSE dá um prompt "Pressione qualquer tecla para continuar ...". Se você não colocar
isso no final do arquivo de lote, o console fechará imediatamente depois que o arquivo
terminar de ser executado. Quando você está escrevendo e depurando o arquivo de lote,
é útil colocar PAUSE no final para poder ver as mensagens de erro que foram impressas
durante a execução do arquivo. Depois que seu arquivo de lote for testado e estiver
funcionando corretamente, você poderá remover a pausa.
133
Arquivos em lote podem conter variáveis, loops, comentários e lógica condicional,
todos os quais estão além do escopo desta lição. No entanto, se você estiver escrevendo e
executando muitos scripts para sua organização, vale a pena gastar algum tempo
aprendendo mais sobre arquivos em lote. Felizmente, os arquivos em lote existem há muito
tempo (são mais antigos que o próprio Windows), portanto, há uma abundância de boas
informações disponíveis na Internet para ajudá-lo.
Agendando tarefas
Neste ponto chegamos muito perto de alcançar a verdadeira automação, mas ainda há
a necessidade de lançar o script Python ou o arquivo em lote, seja clicando duas vezes nele,
chamando-o a partir da linha de comando ou dizendo ao sistema operacional para executá-
lo. Para automatizar verdadeiramente a execução de scripts e arquivos em lotes, você pode
usar um utilitário do sistema operacional, como o Agendador de Tarefas do Windows.
O Agendador de Tarefas é um daqueles itens ocultos nas Ferramentas de Sistema do
Windows que você talvez não tenha prestado atenção antes. É um programa relativamente
simples que permite agendar seus scripts e arquivos em lote para serem executados
regularmente. Isso é útil se a tarefa precisar ser executada com frequência suficiente para
que seja difícil iniciar o arquivo em lote manualmente; mas é ainda mais útil se a tarefa usar
alguns dos seus recursos de computação e você quiser executá-los durante a noite ou no
fim de semana para minimizar o impacto em outras pessoas que possam estar usando o
computador.
Aqui está um cenário do mundo real onde o Agendador de Tarefas (ou um utilitário
comparável se você estiver executando em um Mac, Linux ou UNIX) é muito importante:
Mapas da Web rápidos tendem a usar um cache do lado do servidor de imagens de mapa
pré-geradas, para que o servidor não precise desenhar o mapa toda vez que alguém navegar
para uma área. Um administrador de mapa da Web que tenha o ArcGIS Server pode
executar a ferramenta de gerenciamento de blocos de cache do servidor de mapas para criar
os blocos antes de implantar o mapa da Web. Após a implantação, o servidor envia
rapidamente os blocos apropriados para as pessoas enquanto elas navegam no mapa da
Web. Por enquanto, tudo bem.
No entanto, à medida que os dados SIG de origem do mapa são alterados, os blocos
de cache ficam desatualizados. São apenas imagens e não sabem atualizar-se
automaticamente. O cache precisa ser atualizado periodicamente, mas a criação do bloco
de cache é uma operação demorada e com uso intensivo da CPU. Por esse motivo, muitos
administradores de servidores usam o Agendador de Tarefas para atualizar o cache. Isso
geralmente envolve a gravação de um script ou arquivo em lote que executa o Manage Map
Server Cache Tiles e outras ferramentas de armazenamento em cache, agendando esse
script para ser executado em noites ou fins de semana quando seria menos prejudicial para
os usuários do mapa da web.
Dentro do Windows Task Scheduler
Vamos dar uma olhada rápida no Windows Task Scheduler. As instruções abaixo são
para o Windows 10. Outras versões do Windows têm um Agendador de Tarefas muito
semelhante e, com alguma adaptação, você também pode usar as instruções abaixo para
entender como agendar uma tarefa.
• Digitando Agendador de Tarefas na barra de pesquisa abra o aplicativo.
134
• Na guia de ações clique em Criar Tarefa Básica. Isso leva você através de um assistente
simples para configurar a tarefa. Você pode configurar opções avançadas na tarefa
posteriormente.
• Dê à sua tarefa um Nome que será facilmente lembrado e, opcionalmente, uma
Descrição. Em seguida, clique em Avançar.
• Escolha com que frequência você deseja que a tarefa seja executada. Para este
exemplo, escolha diariamente. Em seguida, clique em Avançar.
• Escolha um horário de início e uma frequência de recorrência. Se você quiser, escolha
um horário alguns minutos antes do horário atual para ver como fica quando uma tarefa
é executada. Em seguida, clique em Avançar.
• Escolha Iniciar um programa e clique em Avançar.
• Aqui está o momento da verdade em que você especifica qual script ou arquivo de lote
deseja executar. Clique em Navegar e navegue até um dos scripts do Python que você
escreveu durante este curso. Será mais fácil se você escolher um script que não aceita
argumentos, como o script do seu projeto 1, que cria linhas de contorno a partir de
conjuntos de dados codificados, mas, se você estiver se sentindo corajoso, também
poderá adicionar argumentos nesse painel. Em seguida, clique em Avançar.
• Revise as informações sobre sua tarefa e clique em Concluir.
• Observe que sua tarefa agora aparece na lista no Agendador de tarefas. Você pode
destacar a tarefa para ver suas propriedades ou clicar com o botão direito do mouse na
tarefa e clicar em Propriedades para realmente definir essas propriedades. Você pode
usar as propriedades avançadas para que seu script seja executado com mais frequência
do que diariamente, por exemplo, a cada 15 minutos.
• Aguarde a hora programada para ocorrer ou, se não quiser esperar, clique com o botão
direito do mouse na tarefa e clique em Executar. De qualquer maneira, você verá uma
janela do console aparecer quando o script começar e desaparecer assim que o script
for concluído. Se você estiver executando um script Python e não quiser que a janela do
console desapareça no final, poderá colocar uma linha no final do script, como lastline =
raw_input(">"). Isso interrompe o script até que o usuário pressione Enter. Uma vez que
você estiver confortável com o script sendo executado regularmente, você
provavelmente desejará remover essa linha para impedir que as janelas de console
permaneçam abertas em sua tela. Afinal, a ideia de uma tarefa agendada é que ela seja
executada em segundo plano sem incomodar você.
135
O Agendador de Tarefas do Windows
Resumo
Para que seus scripts sejam executados automaticamente, use o Agendador de
Tarefas do Windows para criar uma tarefa que o sistema operacional execute em intervalos
regulares. A tarefa pode apontar para um arquivo .py (para um único script) ou um arquivo
.bat (para vários scripts). Usando tarefas agendadas, você pode conseguir a automação
completa de seus processos SIG
136
• Examine os parâmetros. Vá até a seção "Sintaxe" do tópico e leia quais parâmetros a
ferramenta precisa. Observe quais parâmetros são obrigatórios e quais são opcionais e
decida quais parâmetros seu script fornecerá.
• Em seu script Python, crie variáveis para cada parâmetro. Observe que cada parâmetro
na seção "Sintaxe" do tópico tem um tipo de dados listado. Se o tipo de dados para um
determinado parâmetro estiver listado como "String", você precisará criar uma variável
de string para esse parâmetro.
Às vezes, a tradução do tipo de dados para a variável do Python não é direta. Por
exemplo, às vezes, a referência da ferramenta dirá que a variável necessária é uma
"Classe de feições". O que isso realmente significa para o seu script Python é que você
precisa criar uma variável de string contendo o caminho para uma classe de feição.
Outro exemplo é se a referência da ferramenta diz que o tipo de dados requerido é "Inteiro
Longo". O que isso significa no Python é que você precisa criar uma variável numérica
para esse parâmetro em particular.
Se você tiver dúvidas sobre como criar sua variável para corresponder ao tipo de dados
necessário, role para baixo até a "Amostra de código" no tópico de referência da
ferramenta. Tente encontrar o lugar onde o script de exemplo define a variável com a
qual você está tendo problemas. Copie os padrões que você vê no script de exemplo e,
geralmente, você conseguirá resolver o problema.
A maioria das ferramentas usadas tem excelentes scripts de exemplo, mas outras são
imprevisíveis. Se a sua ferramenta de interesse não tiver um bom roteiro de exemplo,
você poderá encontrar algo nos fóruns da ESRI ou em uma pesquisa no Google bem
formulada.
• Execute a ferramenta ... com tratamento de erros. Você pode executar o seu script sem
blocos try / except para capturar erros básicos na Janela Interativa. Se você ainda não
está recebendo nada de útil, o próximo recurso é adicionar os blocos try / except e inserir
comando de print arcpy.GetMessages() no bloco except.
No Projeto 4, você terá a chance de praticar essas habilidades para executar uma
ferramenta com a qual você ainda não tenha trabalhado em um script.
137
• Imprimindo uma série de mapas ou data frames.
• Exportar uma série de mapas para PDF e juntá-los para criar um "livro de mapas".
• Disponibilizando uma série de mapas para outras pessoas no ArcGIS Server.
Os documentos do mapa da ESRI são arquivos binários, o que significa que eles não
podem ser facilmente lidos e analisados usando as técnicas que abordamos anteriormente
nesta lição. Até muito recentemente, a única maneira de automatizar qualquer coisa com um
documento de mapa era usar ArcObjects, o que é um pouco desafiador para iniciantes e
requer o uso de uma linguagem diferente do Python. Com o lançamento do ArcGIS 10.0, a
ESRI adicionou um módulo Python para automatizar tarefas comuns com documentos de
mapas.
O módulo arcpy.mapping
arcpy.mapping é um módulo que você pode usar em seus scripts para trabalhar com
documentos de mapa. Ler a Introdução da ESRI sobre o arcpy.mapping é um importante
começo. http://desktop.arcgis.com/en/arcmap/latest/analyze/arcpy-mapping/introduction-to-
arcpy-mapping.htm
O objeto mais importante neste módulo é o MapDocument. Isto diz ao seu script em
qual mapa você estará trabalhando. Você pode obter um MapDocument referenciando um
caminho, como este:
mxd = arcpy.mapping.MapDocument(r"C:\SEA5923\Dados\Projeto.mxd")
Observe o uso de “r” na linha acima para denotar um literal de string. Em outras
palavras, se você incluir “r” antes de iniciar sua string, é seguro usar caracteres reservados
como a barra invertida \. Eu fiz isso aqui porque você verá em muitos dos exemplos da ESRI
com o arcpy.mapping.
Em vez de usar diretamente um caminho de string, você poderia, alternativamente,
colocar uma variável armazenando o caminho. Isso seria útil se você estivesse percorrendo
todos os documentos de mapa em uma pasta usando um loop ou se obtivesse anteriormente
o caminho em seu script usando algo como arcpy.GetParameterAsText() .
Pode ser conveniente trabalhar com o arcpy.mapping na janela do Python no ArcMap.
Nesse caso, você não precisa colocar o caminho para o MXD. Há uma palavra-chave
especial "CURRENT" que você pode usar para obter uma referência ao MXD aberto no
momento.
mxd = arcpy.mapping.MapDocument("CURRENT")
Depois de obter um MapDocument, você pode fazer algo com ele. A maioria das
funções em arcpy.mapping usa um objeto MapDocument como parâmetro. Vamos ver este
primeiro script, e examinar o que está acontecendo. Eu adicionei comentários para cada
linha.
# Craindo um objeto MapDocument e referenciando o MXD a ser atualizado
mxd = arcpy.mapping.MapDocument(r"C:\SEA5923\Dados\Layout.mxd")
# Percorre cada elemento de texto no documento de mapa
for texto in arcpy.mapping.ListLayoutElements(mxd, "TEXT_ELEMENT"):
# Verifica e o element de texto a data a ser alterada
if texto.text == "Divisão SIG 2015":
# Se o texto for encontrado o substitui para o novo texto
texto.text = "Divisão SIG 2016"
# Exporta o mapa atualizado para um PDF
arcpy.mapping.ExportToPDF(mxd, r"C:\SEA5923\Dados\Laypout_2016.pdf")
# Limpa da memória o objeto MapDocument deletando-o
138
del mxd
A primeira linha no exemplo acima obtém um objeto MapDocument referenciando
C:\SEA5923\Dados\Layout.mxd. O exemplo então emprega duas funções do
arcpy.mapping. O primeiro é ListLayoutElements. Observe que os parâmetros para essa
função são um MapDocument e o tipo de elemento de layout que você deseja recuperar,
neste caso, "TEXT_ELEMENT". (Examine a documentação dos elementos de lista de layout
para entender os outros tipos de elementos que você pode obter de volta.)
A função retorna uma lista Python de objetos TextElement representando todos os
elementos de texto no documento do mapa. Você sabe o que fazer se quiser manipular todos
os itens em uma lista do Python. Nesse caso, o exemplo usa um loop for para verificar a
propriedade TextElement.text de cada elemento. Esta propriedade é legível e gravável, o
que significa que se você quiser definir algum novo texto, basta usar o operador de atribuição
de sinal de igual como em textElement.text = "Divisão SIG 2016"
A função ExportToPDF é muito simples neste script. É preciso um MapDocument e o
caminho do PDF de saída como parâmetros. Se você examinar a documentação do
ExportToPDF, observará muitos outros parâmetros opcionais para exportar PDFs, como, por
exemplo, incorporar fontes, resolução, entre outras que são deixadas como padrões neste
exemplo.
Aprendendo arcpy.mapping
A melhor maneira de aprender o arcpy.mapping é tentando usá-lo. Por causa de sua
natureza simples, pesquisar na internet, é um bom lugar para aprender o arcpy.mapping e
praticar seu Python. Também é uma boa ideia praticar com a janela do Python no ArcMap,
porque você pode ver imediatamente os resultados de suas ações.
Embora não exista nenhum componente arcpy.mapping no projeto desta lição, você
pode usá-lo em seu projeto final. Se você usar o arcpy.mapping no seu projeto final, você
deve tentar incorporar várias das funções ou misturá-las com outras funcionalidades do
Python que você aprendeu, tornando algo mais complexo.
Provavelmente você já experimentou a realidade de que seu código nem sempre é
executado como esperado na primeira tentativa. Antes de começar a executar os comandos
arcpy.mapping nos seus MXDs de produção, sugiro fazer cópias de backup.
Aqui estão alguns lugares adicionais onde você pode encontrar excelente ajuda para
aprender arcpy.mapping:
• Capítulo 10. Zandbergen Eu recomendo que você, pelo menos, leia este capítulo para
ver os tipos de exemplos que estão incluídos.
• Ajuda do módulo Arcpy Mapping do ArcGIS Desktop
http://desktop.arcgis.com/en/arcmap/latest/analyze/arcpy-mapping/introduction-to-
arcpy-mapping.htm
139
ferramentas do ArcGIS. Há muitas opções disponíveis para você por meio de scripts, e
esperamos que você esteja começando a ter ideias sobre como aplicar isso em seu trabalho.
Para concluir esta lição, no entanto, é importante falar sobre o que não está disponível
através do script Python no ArcGIS.
Scripts Python x ArcObjects
No ArcGIS, a interação do Python com o ArcGIS é limitada principalmente à leitura e
gravação de dados, edição das propriedades dos documentos de mapa e execução das
ferramentas incluídas no ArcGIS. Embora as ferramentas do ArcGIS sejam úteis, elas são,
de certa forma, uma caixa preta, o que significa que você coloca as coisas em prática e faz
as coisas sem saber ou se preocupar com o que está acontecendo lá dentro. Se você quer
um maior grau de controle sobre como o ArcGIS está manipulando seus dados, você precisa
trabalhar com ArcObjects.
ArcObjects pode ser considerado como "os blocos de construção" do ArcGIS. Na
verdade, uma analogia com os blocos de construção Lego das crianças funciona bem para
descrever ArcObjects. Programar com ArcObjects é como ter uma enorme seleção de Legos
de todas as formas e tamanhos, enquanto o Python é como trabalhar com um kit contendo
algumas grandes peças pré-fabricadas.
Devido à enorme quantidade de funcionalidades e objetos disponíveis para você, o
ArcObjects é mais desafiador de aprender do que o script Python. Normalmente, uma tarefa
equivalente leva muito mais linhas de código para escrever em ArcObjects do que em um
script Python. No entanto, quando você usa o ArcObjects, você tem muito mais controle
sobre o que acontece no seu programa. Você pode usar uma pequena parte da
funcionalidade e usá-la sem todos os outros parâmetros que acompanham uma ferramenta.
Limites com personalização da interface com o usuário antes do ArcGIS 10.1
Neste curso não fizemos nada com a personalização do ArcMap em si, como adicionar
botões especiais, barras de ferramentas, etc, que acionam nossos programas. Nossa
incursão no design da interface do usuário limitou-se a criar uma ferramenta de script e uma
caixa de ferramentas. Embora as ferramentas de script sejam úteis, há momentos em que
você deseja tirar a funcionalidade da caixa de ferramentas e colocá-la diretamente no
ArcMap como um botão em uma barra de ferramentas. Você pode querer que o botão inicie
uma nova janela com caixas de texto, rótulos e botões criados por você mesmo.
No ArcGIS 10.x, se você quiser colocar funcionalidades ou programas personalizados
diretamente no ArcMap, você precisa usar Visual Basic for Applications (VBA), C ++ ou uma
linguagem .NET (VB.NET ou C #) trabalhando com ArcObjects. A funcionalidade pode ser
tão simples quanto colocar algumas ações personalizadas atrás de um botão (zoom para
um determinado marcador, por exemplo), ou você pode abrir um programa completo
desenvolvido com vários formulários, opções e menus. As linguagens mencionadas acima
têm IDEs nos quais você pode criar interfaces de usuário personalizadas com caixas de
texto, rótulos, botões e assim por diante.
Nova funcionalidade de complementos (add-in) do Python desde o ArcGIS 10.1
Para permitir um maior grau de interatividade entre a interface de usuário do ArcMap e
os scripts do Python, a partir do ArcGIS 10.1 foi introduzido o conceito de um suplemento do
Python. Eles permitem que você anexe a lógica do Python a um conjunto limitado de ações
que você executa no ArcMap, como ampliar o mapa, abrir um novo documento de mapa ou
clicar em um botão em uma barra de ferramentas personalizada. Por exemplo, você pode
140
criar um suplemento que adicione automaticamente um determinado conjunto de camadas
sempre que alguém pressionar um determinado botão na sua barra de ferramentas.
Com os complementos do Python, você obtém acesso a vários elementos da interface
do usuário para usar como front-end em scripts do Python, incluindo barras de ferramentas,
botões, menus, caixas de combinação e navegação básica de arquivos e caixas de diálogo
de confirmação Sim / Não. Há também um conjunto de eventos comuns que você pode
detectar e responder em seu código, como a abertura do mapa, a alteração da extensão do
mapa ou a alteração da referência espacial. Embora isso esteja longe de ser o domínio
completo das possibilidades de personalização do ArcObjects e do .NET, ele oferece muito
mais possibilidades do que as disponíveis nas versões anteriores do ArcGIS.
A coisa boa sobre add-ins é que eles são facilmente compartilháveis. Você faz o
download do Assistente de complementos do Python da ESRI e ajuda a preparar e
empacotar seu suplemento em um arquivo.esriaddin. Outras pessoas com o ArcGIS podem
então instalar o add-in a partir do arquivo.esriaddin.
Trabalhar com suplementos Python atualmente não está incluído no escopo deste
curso, mas você pode aprender tudo sobre eles na ajuda do ArcGIS Desktop no tópico
Python add-ins. Depois de ler este material e obter uma compreensão básica do que é
necessário para criar suplementos, você pode incorporá-los ao seu projeto final se tiver o
ArcGIS 10.1 ou posterior.
http://desktop.arcgis.com/en/arcmap/latest/analyze/python-addins/what-is-a-python-
add-in.htm
O objetivo
Seu trabalho é escrever um script que leia o arquivo de texto e crie um polígono do
limite de estado por meio das coordenadas. Quando você completar com sucesso este
exercício, você deve ser capaz de visualizar o shapefile no ArcCatalog e dizer a qual estado
pertence o limite.
Dicas
Se você está pronto para o desafio deste script, vá em frente e comece a codificar. Mas
se você não sabe como começar, aqui estão algumas dicas:
141
• Neste script, não há linha de cabeçalho para ler. Você tem permissão para usar os
valores de 0 e 1 diretamente em seu código para se referir à longitude e à latitude,
respectivamente. Isso deve realmente tornar o arquivo mais fácil de processar.
• Antes de iniciar o loop pelas coordenadas, crie um objeto Array para manter todos os
pontos de seu polígono.
• Faça um loop em cada coordenada e crie um objeto Point a partir do par de coordenadas.
Em seguida, adicione o objeto Point ao seu objeto Array.
• Depois de terminar o loop, crie um cursor de inserção no seu shapefile. Vá para a primeira
linha e atribua o Array ao campo SHAPE.
Exercício 2 – Futebol
Este exercício prático não trata diretamente de geoprocessamento, mas ajudará você
a obter alguma experiência trabalhando com funções e dicionários. Este último será
especialmente útil ao trabalhar no Projeto 4.
O objetivo
Você recebeu um arquivo de texto com partidas de futebol (completamente fabricadas)
de algumas das equipes mais populares da Argentina. Escreva um script que leia os gols
em cada partida de cada equipe e imprima o nome de cada equipe, seguido pelo número
máximo de gols que a equipe marcou em um jogo, por exemplo:
River: 5
Racing: 4
etc...
Tenha em mente que o número máximo de gols marcados pode ter ocorrido durante
uma derrota.
Você é deve usar dicionários para completar este exercício. Esta é provavelmente a
maneira mais eficiente de resolver o problema. Você também poderá escrever pelo menos
uma função que reduzirá o código repetido.
Eu intencionalmente mantive este arquivo de texto curto para simplificar as coisas.
Esse é um excelente exercício para usar o depurador, especialmente para verificar o seu
dicionário enquanto você percorre cada linha de código.
O arquivo txt está delimitado por espaço, portanto, você deve configurar explicitamente
o leitor de CSV para usar um espaço como o delimitador em vez da vírgula padrão. A sintaxe
é a seguinte:
leitorCSV = csv.reader (arquivo, delimiter = " ")
Dicas
Aqui estão algumas dicas que podem ajudar você a começar:
• Crie variáveis para todos os seus itens de interesse, incluindo vencedor, golsGanhador,
perdedor e golsPerdedor e atribua a eles os valores apropriados com base no que você
analisou da linha de texto. Como muitas vezes existem empates no futebol, o termo
"vencedor" neste contexto significa o primeiro time da linha e o termo "perdedor" significa
o segundo time da linha.
142
• Analise o capítulo 6.8 sobre dicionários no texto de Zandbergen. Você quer criar um
dicionário que tenha uma chave para cada equipe e um valor associado que represente
o número máximo de gols da equipe. Se você olhou para o dicionário no depurador, ele
se pareceria com {'River': '5', 'Racing': '4', etc.}
• Você pode escrever uma função que aceita três parâmetros: a chave (nome da equipe),
o número de gols e o nome do dicionário. Esta função deve então verificar se a chave
tem uma entrada no dicionário. Caso contrário, uma chave deve ser adicionada e seu
valor definido para o número atual de gols. Se uma chave for encontrada, você deve
executar uma verificação para ver se o número atual de gols é maior que o valor
associado a essa chave. Se assim for, você deve definir um novo valor. Observe quantos
"ifs" aparecem nas sentenças anteriores.
143
Um esforço adicional pode incluir (mas não se limita a) um arquivo em lote que pode
ser usado para automatizar o script, criar uma classe de feições em um arquivo geodatabase
em vez de um shapefile ou a quebra de código repetitivo em funções e / ou módulos.
Desafios
Você já pode ver vários desafios imediatos nesta tarefa:
• Os rinocerontes na planilha eletrônica aparecem sem nenhuma ordem garantida, e nem
todos os rinocerontes aparecem no início da planilha. Ao analisar cada linha, você deve
determinar a qual rinoceronte pertence a leitura e atualizar a polilinha desse rinoceronte
de acordo. Você não tem permissão para classificar a coluna Rinoceronte em um
programa de planilha antes de escrever o script. Seu script deve ser "inteligente"
o suficiente para trabalhar com uma planilha não classificada na ordem em que os
registros aparecem.
• Você não sabe imediatamente quantos rinocerontes estão no arquivo ou até mesmo
quais são seus nomes. Embora você possa visualmente vasculhar a planilha para obter
essas informações e codificar permanentemente o nome de cada rinoceronte, seu script
deve manipular todos os nomes de rinoceronte programaticamente. A ideia é que você
possa rodar este script em um arquivo diferente, possivelmente contendo mais
rinocerontes, sem ter que fazer muitos ajustes manuais.
• Você não criou anteriormente uma classe de feições programaticamente. Você deve
encontrar e executar ferramentas de geoprocessamento do ArcGIS que criarão um
shapefile de polilinha vazia com um campo de texto para armazenar o nome do
rinoceronte. Você também deve atribuir o sistema de coordenadas geográficas do WGS
1984 como a referência espacial para este shapefile.
Dicas
• Antes de começar a escrever o código, escreva um algoritmo descrevendo a lógica que
seu script usará para realizar essa tarefa. Divida a tarefa original em pequenos pedaços
concentrados. Você pode escrever isso no Word ou no Notepad. Seu objetivo não é
escrever texto completo, mas declarações breves e concisas sobre o que seu código
fará: em outras palavras, pseudocódigo. Aqui está um exemplo de alguns pseudocódigos
que podem aparecer no seu arquivo:
Leia a próxima linha.
Puxe os pedaços de informação necessários da linha (lat, lon, name)
Determine se o dicionário tem uma chave para o nome do rinoceronte.
Se nenhuma chave existir, crie um novo objeto de matriz.
Crie um novo objeto de ponto.
Atribuir a leitura lon à coordenada X do ponto.
Atribua a leitura Y à coordenada lat do ponto.
Adicione o ponto à matriz.
Adicione a matriz ao dicionário usando o nome do rinoceronte como a chave.
...
Se você fizer um bom trabalho escrevendo seu pseudocódigo, verá que cada linha se
traduz em uma linha de código. Escrever seu script torna-se uma questão de tradução
do texto para o código. Você também pode achar útil esboçar um diagrama de fluxo de
trabalho e ramificações logísticas em seu script.
144
• Você terá pode agilizar a tarefa se primeiro criar os objetos de matriz representando cada
trilha de rinoceronte e, em seguida, usar os cursores de inserção para adicionar as
matrizes depois que elas forem concluídas. Não só é mais fácil de codificar, mas é melhor
para o desempenho abrir o cursor de inserção apenas uma vez perto do final do script.
• Um dicionário Python é uma excelente estrutura para armazenar um nome de
rinoceronte, juntamente com a matriz de locais observados do rinoceronte. Um dicionário
é semelhante a uma lista, mas armazena itens em pares de valores-chave. Por exemplo,
uma chave poderia ser uma cadeia representando o nome do rinoceronte e o valor
correspondente dessa chave poderia ser um objeto Array contendo todos os pontos em
que o rinoceronte foi observado. Você pode recuperar qualquer valor com base em sua
chave e também pode verificar se existe uma chave usando um comando if simples em
uma função de verificação do dicionário.
Nós não trabalhamos muito com dicionários neste curso, mas no texto do Zandbergen
tem uma seção excelente sobre eles e há exemplos abundantes de dicionários em
Python na Internet.
Como alternativa, você pode usar listas para armazenar as informações, mas isso
provavelmente exigirá mais código. Usando dicionários, consegui escrever este script em
menos de 65 linhas (incluindo comentários e espaço em branco). Se você estiver ficando
confuso ou escrevendo muito código com listas, você pode tentar mudar para dicionários.
• Para criar seu arquivo shape programaticamente, use a ferramenta CreateFeatureClass.
A Ajuda do ArcGIS Desktop tem vários exemplos de como usar essa ferramenta. Se você
não conseguir descobrir essa parte, sugiro que crie a classe de feições manualmente e
trabalhe para escrever o restante do script. Você pode retornar a essa parte no final se
tiver tempo.
• Para obter o shapefile no WGS 1984, você precisará criar um objeto de referência
espacial que possa ser atribuído ao shapefile no momento em que for criado. Eu
recomendo usar o método arcpy.SpatialReference(). Esteja avisado que, se você não
aplicar corretamente a referência espacial, sua precisão de polilinha poderá ser diluída.
Se você fizer as coisas corretamente, suas polilinhas devem ficar assim (os pontos são
incluídos apenas para referência):
145
Nota:
Embora eu tenha colocado os dados em um contexto africano (quem ouviu falar de
rinocerontes perambulando pelo _______?), Ele é completamente fabricado e não se parece
com o caminho de qualquer rinoceronte real, vivo ou morto.
146
Solução dos Exercícios Práticos:
Etapa 2
Exercício 1: Encontrar os espaços em uma lista de nomes
beatles = ["John Lennon", "Paul McCartney", "Ringo Starr", "George
Harrison"]
for cantor in beatles:
espaco = cantor.index(" ")
print ("Há um espaço no nome de " + cantor + " na posição " +
str(espaco) + ".")
Explicação:
Dada a informação sobre o método de índice nas instruções, o truque para este
exercício é aplicar o método a cada string da lista. Para percorrer todos os itens em uma
lista, use uma instrução for que termine com 'in <list variable>', que nesse caso era chamado
beatles. Entre as palavras 'for' e 'in' você insere uma variável com um nome de sua escolha.
Essa variável armazenará um item de lista diferente em cada iteração por meio do loop.
Na minha solução, chamei essa variável de “cantor”. A variável “cantor” assume o valor
de "John Lennon" na primeira passagem pelo loop, "Paul McCartney" na segunda passagem
pelo loop, etc. A posição do primeiro espaço na variável é retornada pelo método de índice
e armazenado em uma variável chamada “espaço”.
A última etapa é conectar o nome do membro do grupo e a posição do espaço na
mensagem de saída. Isso é feito usando o caractere de concatenação de string (+). Observe
que a variável “espaço” deve ser convertida em uma string antes de poder ser concatenada
com o texto literal.
147
Exercício 3: Converter pontuações em notas de letra
import arcpy
entrada = arcpy.GetParameterAsText(0)
escore = int(input)
if escore > 89:
print ("A")
elif escore > 79:
print ("B")
elif escore > 69:
print ("C")
elif escore > 59:
print ("D")
else:
print ("F")
Explicação:
Este exercício requer a aceitação de um parâmetro de entrada, portanto, na minha
solução, importei o arcpy para poder usar o método GetParameterAsText. Se você executar
este script diretamente no PythonWin, poderá fornecer o valor de entrada para
GetParameterAsText colocando-o no campo Arguments da caixa de diálogo "Run Script"
que é aberta quando você clica em "Run". Uma alternativa ao uso de GetParameterAsText
seria usar a função raw_input() do Python para ler o teclado. Como o parâmetro de entrada
está sendo armazenado como uma string, inclui-se uma etapa adicional que converte o valor
dessa string em um inteiro. Embora não seja crítico nesse caso, geralmente é uma boa ideia
evitar o tratamento de valores numéricos como sequências de caracteres quando possível.
Por exemplo, o número 10 tratado como uma string ("10") é considerado menor que “2”
porque o primeiro caractere em “10” é 1 que é menor que 2.
Um bloco 'if' é usado para imprimir a nota apropriada para a pontuação inserida. Você
pode estar se perguntando por que todas as expressões tratam apenas da extremidade
inferior da faixa de notas e não da extremidade superior. Embora isso certamente funcione
para especificar os dois extremos do intervalo (por exemplo, 'escore elif> 79 and escore
<90:'), não é realmente necessário se você avaliar o código como o intérprete faria. Se o
usuário inserir um valor maior que 89, a declaração ''print ('A')'' será executada e todas as
outras condições associadas ao bloco if serão ignoradas.
Isto significa é que a condição de elif 'escore > 79' só será alcançada se a pontuação
não for maior do que 89. Isso torna desnecessário especificar a extremidade superior da
série. A mesma lógica se aplica ao restante das condições no bloco.
148
Explicação:
Este script começa inicializando o objeto de geoprocessamento, configurando o espaço
de trabalho e selecionando a caixa de ferramentas que contém a ferramenta desejada. Uma
referência ao shapefile a ser copiado é armazenada em uma variável chamada de “modelo”.
Como a ideia é criar uma cópia desse shapefile para cada ano de 2019-2022, uma
abordagem lógica é configurar um loop for definido com limites de 'in range (2019,2023)'.
(Lembre-se de que a extremidade superior do intervalo deve ser especificada como 1 maior
que o ponto final real desejado).
Dentro do loop, o nome do novo shapefile é reunido pela concatenação do número
mantido na variável “ano” com as partes antes e depois que são sempre as mesmas. A
ferramenta CreateFeatureClass pode então ser chamada, fornecendo-se o local de trabalho
desejado para a classe de feição de saída, seu nome, seu tipo de geometria, a classe de
feições a ser usada como modelo de esquema, se a classe de feições deve ser configurada
para armazenar valores m e z e finalmente um argumento da referência espacial. Observe
na documentação que a referência espacial da classe de feições de saída pode ser
especificada de várias maneiras diferentes e será indefinida se um argumento de referência
espacial não for fornecido (ela não assume automaticamente a referência espacial da classe
de feições usada como modelo de esquema).
149
Explicação:
Inicialmente importamos o módulo arcpy. Isso é necessário sempre que trabalhamos
com ferramentas ou conjuntos de dados ESRI.
Nas linhas seguintes, configuramos uma série de variáveis de string representando os
locais no disco com os quais trabalharemos durante esse script. Agora, se você fosse criar
uma ferramenta de script, você eventualmente desejaria alterá-los para um parâmetro do
tipo arcpy.getParameterAsText(), conforme descrito no texto da lição. No entanto, enquanto
estiver trabalhando em seu script no PythonWin, você vai querer realmente escrever o
caminho completo para que possa testar e certificar-se de que seu script funciona. Uma vez
que você esteja absolutamente certo de que seu script funciona, então você pode ir em frente
e inserir a função arcpy.getParameterAsText.
Configuramos os caminhos dos geodatabases para as variáveis “entrada” e “destino”
A variável “entrada” aponta para o geodatabase que contém as classes de feições que serão
recortadas. A variável “destino” aponta para o geodatabase de saída, onde armazenaremos
as classes de feições recortadas. A variável clipFC aponta para a classe de feições que é o
limite da região para a qual se deseja recortar as classes de feições de entrada.
Existe como configurar um local de trabalho para o arcpy, que é a pasta atual ou
geodatabase na qual o arcpy está procurando itens nós definimos o arcpy workspace como
o mesmo caminho que configuramos para os dados de entrada.
Agora é necessário chamarmos o método para listar as classes de feições e a questão
é, listar as classes de feições de onde? A resposta é o local de trabalho que acabamos de
configurar, portanto, é padrão procurar no local de trabalho do arcpy pelas classes de feições
que ele deve listar. E então o que nós tiramos disso é uma variável que chamamos de fcLista
e é uma lista Python de todas as classes de feições no geodatabase de entrada. Isso é ótimo
agora porque sabemos como percorrer uma lista e vamos fazer isso agora.
Começamos um bloco try, então tentaremos executar todo o código dentro desse
bloco, se por algum motivo houver um travamento, o código pula para o bloco except.
No bloco try iniciamos um loop for para tentar percorrer cada classe de feições na lista.
Assim criamos uma nova variável chamada “fc” que representará cada classe de feições da
lista a cada looping.
Temos que configurar o caminho de saída. Agora, um de nossos requisitos era anexar
“-Clip” no fim do nome da classe de feições de saída e, portanto, estamos fazendo um pouco
de manipulação de string usando o sinal de mais para criar um caminho. Essa string
específica “saidaFC” será criada pela concatenação da variável de destino. Isso sempre fará
parte do caminho de saída. Então, vamos adicionar o nome da classe de feições com a qual
estamos trabalhando atualmente e, em seguida, adicionaremos explicitamente o “_Clip”.
Devemos então executar o recorte chamando o método arcpy.Clip_analysis. Agora,
neste caso, o método tem três parâmetros obrigatórios: a classe de feições de entrada a ser
recortada, esse é o primeiro parâmetro “fc”. O segundo parâmetro é o “clipFC” que
corresponde ao limite para o recorte. E então o terceiro parâmetro é o caminho de saída, e
esse é o caminho que acabamos de criar, e assim que tivermos todas essas três coisas,
podemos executar a ferramenta.
Relatamos o que aconteceu e usamos um pouco de concatenação de strings lá para
criar uma mensagem personalizada dizendo exatamente o caminho do arquivo recortado
que criamos. Agora, esse é um cenário que você poderia ou adicionar uma mensagem ou
fazer uma declaração impressa. Aqui colocamos as duas formas para que você possa ver
150
como ambos foram usados. Se você for seguir em frente e criar uma ferramenta de script a
partir disso, que irá em sua caixa de ferramentas no ArcGIS, então você usaria a abordagem
de adicionar mensagem. Se você for rodar apenas dentro de um PythonWin, então você
usaria a impressão. Se por algum motivo houvesse um travamento no código acima, ele
saltaria para para o bloco except, onde as mensagens de erro são apresentadas ao usuário.
Etapa 3
Exercício 1
Abaixo está uma solução possível para o exercício 1 com comentários para explicar o
que está acontecendo. Se você encontrar uma maneira mais eficiente de codificar uma
solução, compartilhe-a. Note que, a fim de fazer as alterações para "cidadesLayer"
permanente (salvá-las), você tem que gravar a camada no disco usando a função
arcpy.CopyFeatures_management(..). Isso não é mostrado nesta solução.
# Este script determina a porcentagem de cidades que contêm postos Flu
import arcpy
arcpy.env.overwriteOutput = True
cidades = "C:\\SEA5923\\Dados\\BD.gdb\\Cidades"
postosFlu = "C:\\SEA5923\\Dados\\BD.gdb\\estacoesFlu"
campoPostos = "estFlu" # Nome da coluna com a informação sobre os postos
cidadesComPostos = 0 # Usado para contar as cidades com postos
try:
# criando uma feature layer de todos os postos
arcpy.MakeFeatureLayer_management(postosFlu, "postosFluLayer")
# criando uma feature layer de todas as cidades
arcpy.MakeFeatureLayer_management(cidades, "cidadesLayer")
except:
print ("Não foi possível criar os layers")
try:
# Selecionandoo na camada cidades aquelas que contêm postos
arcpy.SelectLayerByLocation_management("cidadesLayer", "CONTAINS",
"postosFluLayer")
151
Explicação:
O script começa importando o pacote do site arcpy.
A seguir alteramos o valor de propriedade de arcpy.env.overwriteOutput para True, o
que é útil quando você está escrevendo scripts como estes, onde você estará fazendo alguns
testes e frequentemente vai querer sobrescrever os arquivos de saída. Caso contrário, o
ArcGIS retornará uma mensagem de erro informando que ele não pode sobrescrever uma
saída que já existe, então essa é uma dica a ser retirada deste código.
Nas linhas seguintes são declaradas as variáveis de string que que têm os caminhos
para as classes de feições com as quais trabalharemos, a classe de feições Cidades e a
classe de feições EstacoesFlu, ambos do banco de dados geográficos BD.gb. Também
atualizamos um campo da classe de feições Cidades chamado “estFlu”. Vamos defini-lo para
verdadeiro ou falso. Então uma variável é criada para isso, vamos chamá-la de
“campoPostos”. E você a verá usada depois.
A seguir declaramos um contador que será usado no código para contar o número de
cidades com pelo menos 1 posto. Iniciamos o contador no zero.
Iniciamos um bloco try-except, de código. Nesta solução, mostro alguns exemplos de
como você pode manipular erros e retornar mensagens. Normalmente, se você deixar isso
de fora, seu script retornará boas mensagens de erro para você, que você pode usar para
descobrir qual linha falhou. No entanto, se você distribuir seus scripts para um usuário final,
eles desejarão ver mensagens mais agradáveis.
Você pode colocar suas próprias mensagens personalizadas como eu fiz. Mas por
enquanto temos um bloco try.
E vamos tentar fazer duas camadas de recursos. Faremos uma camada de feição que
tenha todo os postos e uma camada de feição que tenha todos os limites das cidades. E
para ambos, a ferramenta MakeFeatureLayer tem dois parâmetros que nós fornecemos, o
nome da classe de feição que vai agir como a camada de feição e então o segundo
parâmetro é um nome que usaremos para nos referirmos. a esta camada de feição em todo
este script e apenas este script, então este é um nome que está na memória do computador.
Por exemplo, para a camada de postos, chamamos apenas de postosFluLayer. Podemos
nomear essa parte do que quisermos.
Então nós temos essas duas camadas de feições que agora podemos fazer seleções.
Vamos fazer uma seleção de localização para selecionar todas as cidades que contenham
feições da camada de postos. Às vezes é útil fazer isso no ArcMap para ver o que está
acontecendo.
E uma vez que você tenha essa seleção, você pode fazer coisas com ela. Então, por
exemplo, no ArcMap, se eu quisesse trabalhar com essas cidades, eu poderia abrir a tabela
de atributos. E veríamos que alguns registros estraiam selecionados. E então poderiamos
apenas trabalhar nessas linhas selecionadas para fazer alguma coisa.
Então, vamos fazer isso no Python abrindo um cursor de atualização. E o cursor está
indo trabalhar apenas nessa camada reduzida de cidades. Por isso, é importante notar que
você começou com a camada de cidades que tinha todas as cidades. E depois de executar
a seleção, essa camada só irá conter um subconjunto selecionado dessas cidades. E é isso
que vai ser aplicado no seu cursor de atualização.
Portanto, este cursor de atualização não atualizará tudo. Apenas atualizará as cidades
atualmente selecionadas. E só poderá atualizar os campos especificados no segundo
152
parâmetro. Então, onde coloquei campoPostos e, em seguida, uma vírgula, que é uma tupla,
uma tupla Python, com um item nela que representa o campo que vou editar.
E então o que temos é um cursor que pode ir de linha a linha. E fazemos isso usando
o loop for, que está a seguir. Pegamos então esse campo estFlu e o configuramos como
“Verdadeiro”.
Agora por que usa-se 0 entre colchetes? 0 é a posição do índice do campo que eu
passei naquela tupla. E foi passado em uma tupla com apenas um campo, campoPostos.
Depois de fazer essas alterações, precisa-se chamar updateRow para que elas sejam
aplicadas. E isso é um erro que muitos iniciantes cometem.
A seguir incrementa-se o contador que mantem o número de cidades com postos
encontradas. Então adicionamos 1 ao contador. O += 1 é um atalho para dizer, pegue esse
número e adicione 1.
Iniciamos agora um bloco finally, que seria executado se o código acima falha-se ou
não. Ele limpa essas camadas de feição para que não fiquem presas na memória do
computador. Eu poderia colocá-los em um bloco de exceção talvez, mas eu prefiro colocá-
los em um bloco finally porque eles precisam ser limpos da memória mesmo se o script falhar
ou não.
Agora é hora de fazer algumas contas para descobrir a porcentagem de cidades que
têm pelo menos 1 posto. Executando a ferramenta GetCount, e podemos executar essa
ferramenta diretamente em uma classe de feições. Então aqui eu não preciso de uma
camada de feição. Acabamos de passar o caminho da string para uma classe de feições,
observe que fazemos referência a variável Cidades. Essa é uma variável que foi criada lá no
início e só tem o caminho para os dados.
Quando você usa a ferramenta GetCount, você também deve chamar um método
getOutput para obter o resultado real e convertê-lo em um inteiro. Agora isso é um pouco
complexo. Não se preocupe se você não entender tudo. Mas basta seguir os exemplos que
estão neste código ou também o código de ajuda do ArcGIS para a ferramenta GetCount.
Então, o que temos no final, é uma variável chamada totalCidadesInt, que é o número
total de cidades em todo o conjunto de dados. Como já temos o contador de cidades com
pelo menos 1 posto, para encontrar a porcentagem, tudo o que precisamos fazer é dividir
um pelo outro.
Agora, há algumas coisas extras na equação aqui. Nós usamos 1.0 e multiplicamos
pelo número de cidades com um posto, porque queremos fazer uma divisão decimal. Se não
fizéssemos isso, ele executaria a divisão inteira por padrão. E também multiplicamos por
100 para obter um percentual interpretável. Por fim podemos imprimir o resultado no final do
script.
Exercício 2
Abaixo está uma solução possível para o exercício 1 com comentários para explicar o
que está acontecendo.
153
arcpy.env.overwriteOutput = True
cidades = "C:\\SEA5923\\Dados\\BD2.gdb\\Cidades"
postosFlu = "C:\\SEA5923\\Dados\\BD2.gdb\\estacoesFlu"
campoPostos = "estFlu" # Nome da coluna com a informação sobre os postos
geocodigo = "GEOCODIGO" # Nome da coluna com os IDs para as cidades
cidadesCom5Postos = 0 # Usado para contar cidades com mais de 5 postos
numCidades = 0 # Usado para contar o total de cidades
# criando uma feature layer de todos os postos
arcpy.MakeFeatureLayer_management(postosFlu, "postosFluLayer")
# Criando um update cursor e percorrendo cada cidade
with arcpy.da.UpdateCursor(cidades, (geocodigo, campoPostos)) as cidRows:
for cid in cidRows:
# Create a query string for the current city
cidID = int(cid[0])
expSQL = '"' + geocodigo + '" = ' + str(cidID)
# Criando uma feature layer somente da cidade atual
arcpy.MakeFeatureLayer_management(cidades, "cidLayer", expSQL)
try:
# Selecionando os postos apenas da cidade atual
arcpy.SelectLayerByLocation_management("postosFluLayer",
"CONTAINED_BY", "cidLayer")
# contando o número de postos selecionados
contadorPostosSel=
arcpy.GetCount_management("postosFluLayer")
numContadorPostosSel = int(contadorPostosSel.getOutput(0))
# Se 5 postos ou mais forem encontrados, atualiza o campo
if numContadorPostosSel >= 5:
cid[1] = "Verdadeiro"
# Não esquecer de atualizar chamando updateRow
cidRows.updateRow(cid)
# incrementa o contador de cidades com 5 postos
cidadesCom5Postos += 1
finally:
# Deletando o layer de cidade atual para o próximo loop
arcpy.Delete_management("cidLayer")
numCidades += 1
# Limpando a feature layer dos postos
arcpy.Delete_management("postosLayer")
del cid, cidRows
# Calculando e print o nr de cidades selecionados com 5 ou mais postos
if numCidades <> 0:
perCidadesComPostos = ((1.0 * cidadesCom5Postos) / numCidades) * 100
print (str(perCidadesComPostos) + r" % das cidades contém 5 postos.")
else:
print ("Erro com os dados de entrada. Não foram encontradas cidades")
Explicação:
Temos uma solução possível para o 3xercício 3, que calcula o percentual de cidades
no conjunto de dados com pelo menos cinco postos fluviométricos usando seleções no
ArcGIS. Ele também usa um cursor de atualização para atualizar um campo indicando se a
cidade tem pelo menos cinco ou mais postos. O início deste script é muito semelhante ao
exercício 2, então não vamos gastar muito tempo com isso.
Iniciamos configurando variáveis para referenciar alguns campos que serão
necessários. Parte do exercício é atualizar um campo chamado estFlu para ser verdadeiro
154
ou falso. Então definimos uma variável para isso. A seguir configuramos uma variável para
o código da cidade. Vamos consultar cada cidade uma a uma e precisamos de algum campo
com valores únicos para cada cidade. Poderíamos usar o nome da cidade, mas isso seria
perigoso no caso de você ter um conjunto de dados em que duas cidades tenham o mesmo
nome. Então, vamos usar o código GEOCODIGO por ser um identificador único.
Seguimos configurando alguns contadores que são usados para contar o número de
cidades em que se têm pelo menos cinco postos e, em seguida, o número total de cidades,
respectivamente.
Começamos fazendo uma camada de feições apenas dos postos. E isso é familiar a
partir do exercício anterior, onde o primeiro parâmetro que eu passo é o caminho para o
conjunto de dados dos postos e, em seguida, o segundo parâmetro é um nome que eu dou
a essa camada de recurso. Para os propósitos deste script, chamaremos de postosFluLayer.
Abrimos um cursor de atualização em todos os limites de cidades. Então, percorre-se
cada cidade e seleciona-se o número de postos que ocorrem em cada cidade para
contabilizá-los. Vamos trabalhar com dois campos para este cursor. Passamos isso em uma
tupla. Isso é geocodigo e campoPostos. E essas são as variáveis que foram configuradas
anteriormente no script.
Pode ser útil neste momento dar uma olhada no que estamos fazendo conceitualmente
no ArcMap. Então, a primeira coisa que vamos fazer é uma consulta de atributo para cidades
pelo campo geocodigo. E assim, por exemplo, se eu fosse fazer isso para a cidade de Vitória,
código da cidade é esse número longo aqui 3205309.
E se eu fosse perguntar isso, eu teria como resposta apenas uma cidade. Assim,
restringe-se a camada de feições de cidades para a camada de feições com apenas a cidade
pesquisada.
Faz-se agora a seleção por localização onde seleciona-se os postos que estão
completamente dentro da camada do limite da cidade. Fazendo isso, receberíamos esses
pontos de volta. No que poderíamos contá-los e verificar se atingimos pelo menos cinco, a
fim de determinar se a cidade tem pelo menos cinco postos.
Seguiríamos para a próxima cidade e a próxima cidade e assim por diante até que eu
tivesse trabalhado todo o conjunto de dados. Portanto, há algum processamento que
ocorrerá enquanto você executa o script. Pode demorar alguns segundos para ser
executado.
Tudo certo. Então, estamos de volta onde configuramos o cursor de atualização. Nós
chamamos de cidRows. E então podemos percorrer cada cidade com esse cursor. Então,
isso é o que é feito com um loop for.
Obtemos o código da cidade que está sendo analisada pelo cursor usando “cidID =
int(cid[0])”. Nós usamos 0 lá porque essa é a posição de índice do geocodigo que colocamos
na tupla. Foi o primeiro parâmetro na tupla, então ela tem a posição de índice 0. Como o
campo na tabela de atributos é do tipo Double, usamos o método int para convertê-lo, caso
contrário o valor retornado teria o ponto decimal.
A seguir estamos configurando uma string para consultar o código dessa cidade, ou
seja construímos a expressão SQL que será passada como parâmetro. E então precisamos
que o nome do campo seja igual ao nome que consta na tabela de atributos. Além disso o
nome do campo tem que estar entre aspas duplas. O código da cidade tem que estar sem
aspas. Então isso envolve muita concatenação de strings para acertar a expressão, em que
o código ainda é convertido pelo método str..
155
Mas assim que tivermos essa string, podemos criar uma camada de feição que tenha
apenas uma cidade dentro dela. A maneira como fazemos isso é com a ferramenta
MakeFeatureLayer. Mas em vez de dois parâmetros, colocamos três.
Os dois primeiros parâmetros são os mesmos de quando fizemos a camada de feição
para os postos. Então nós colocamos - é o mesmo padrão. Colocamos o caminho para o
conjunto de dados. Colocamos um nome para essa camada de feição. E aqui chamamos de
cidLayer.
Mas então o terceiro parâmetro é aquela string de consulta que acabamos de criar. E
isso faz com que nossa camada de feição tenha apenas uma cidade que é retornada por
aquela consulta.
Agora vamos fazer a seleção de localização para selecionar apenas os postos que
estão contidos naquela cidade. Os parâmetros aqui são um pouco intuitivos se você tiver
essa compreensão conceitual de como a seleção está funcionando, onde apenas um limite
da cidade está selecionando um subconjunto de postos.
Nesse ponto, você pode chamar uma ferramenta GetCount e descobrir quantos postos
foram de fato selecionados. E lembre-se que você precisa chamar getOutput para obter o
resultado da ferramenta GetCount. Você foi exposto a isso na solução para o exercício 1.
Então, no final, o que você tem é uma variável chamada numContadorPostosSel. Esse
é o número de postos que estão dentro do limite daquela cidade.
Com um comando if / else você pode verificar se esse número é maior ou igual a cinco.
Se for, então vamos definir o valor do campo desejado como Verdadeiro. Então é aí que nós,
usando nosso cursor, vamos pegar o segundo item da tupla, mas mas que na verdade tem
a posição de índice 1, e nós definimos este objeto para Verdadeiro. E não podemos esquecer
de chamar updateRow para que isso seja aplicado ao conjunto de dados.
E então, no final, podemos atualizar nosso contador de cidades que têm pelo menos
cinco postos.
Finalmente, depois de terminarmos todo esse loop, excluímos a camada de feição. Nós
limpamos tudo. E incrementamos o número de cidades que contamos até aqui. E assim
fazemos isso para cada cidade do conjunto de dados.
Por fim nós limpamos a camada de feições dos postos. Note que há alguns níveis de
recuo aqui mostrando o if-then e o try e finalmente e o loop que executa o cursor. Precisamos
administrar isso com cuidado. Se sairmos do recuo, isso significa que estamos saindo do
bloco de código, seja fora da instrução if ou fora do loop try e assim por diante.
Então, depois de fazer a limpeza, agora vamos calcular a porcentagem de cidades que
têm pelo menos cinco postos. Um cuidado, você não pode dividir por zero, então estamos
fazendo uma verificação para evitarmos isso. Mas se tudo der certo, o que aconteceria a
menos que tivéssemos um grande problema com nosso conjunto de dados, seguiríamos em
frente e executaríamos uma divisão para dividir o número de cidades com cinco ou mais
postos pelo número total de cidades. Como no exercício 1 usamos a multiplicação por 1.0 e
por 100.
Para o tratamento de erros que ocorreria se o conjunto de dados de entrada fosse
inválido e não houvesse cidades nele, poderíamos imprimir uma mensagem de advertência.
Caso contrário, seria impresso a porcentagem de cidades que contém os cinco ou mais
postos.
156
Exercício 3
Abaixo está uma abordagem do Exercício 3. O valor do campo a ser consultado é
armazenado em uma variável no topo do script.
# Seleciona postos fluviométricos em operação e os exporta para uma
# nova feature class usando a ferramenta CopyFeatures
import arcpy
emOperacao = "Sim"
arcpy.env.workspace = "C:\\SEA5923\\Dados\\BD.gdb"
# Construindo a expressão SQL para a consulta
expressaoSQL = '"Operando" > ' + emOperacao
# Cria uma feature layer dos postos SQL expression
arcpy.MakeFeatureLayer_management("EstacoesFlu", "postosFluLayer",
expressaoSQL)
# Copia as feições da seleção para uma nova feature class
arcpy.CopyFeatures_management("postosFluLayer", "EstFluOperando")
arcpy.Delete_management("postosFluLayer")
Explicação:
Depois de importar o pacote do módulo arcpy, configuramos a variável que representa
as estações em operação. Então, neste caso, definimos esse valor para “Sim” que é o valor
armazenado na tabela de atributos.
Colocar a variável na parte superior do script é útil para que ela não seja esquecida
posteriormente em nosso código. Então, se quisermos ajustar esse valor e testar com outros
valores, é fácil encontrá-la.
Seguimos configurando o local de trabalho arcpy para ser igual à localização do arquivo
geodatabase. É uma boa escolha trabalhar com file geodatabases, no sentido de que, a
partir de agora, se você se referir a uma classe de feições, você só precisará usar seu nome.
Você não precisa colocar todo o caminho. E você verá que isso ocorre mais tarde nesse
script.
A linha mais crítica desse script é a de configuração da expressão de consulta SQL
para obter os postos em operação. Então, se você olhasse isso no ArcMap, faríamos um
Select By Attributes. E nós consultamos o atributo “Operando” igual a ‘Sim’.
O nome do campo, você tem que colocar em aspas duplas, e é por isso que eu tenho
esta parte da expressão com aspas simples, como você aprendeu em seus exercícios
anteriores.
Depois de configurar essa string de consulta, você pode executar o MakeFeatureLayer
para obter uma Camada de feições dos postos selecionados apenas que atendem ao critério
da consulta.
Então, há três parâmetros para passar aqui. O primeiro é o nome da classe de feições
que estava operando. E mais uma vez, porque montamos o local de trabalho, podemos
apenas colocar que estamos trabalhando com o EstacoesFlu.
O segundo parâmetro é o nome da camada de feição. E nós poderíamos nomear
qualquer nome. Ele só vai residir na memória do computador, desde que seja consistente.
E então o terceiro parâmetro é a expressão de consulta SQL. Isso é opcional. Se
omitíssemos isso, teríamos todas as feições. Mas queremos apenas ter as que atendam aos
critérios.
157
Quando tivermos essa camada de feição, podemos executar a ferramenta de cópia de
feições para criar uma nova classe de feições apenas com esses elementos selecionados.
Então os dois parâmetros aqui - o primeiro é o nome da camada de feição com a qual
estamos trabalhando. E, lembre-se que chamamos isso de postosFluLayer.
O segundo parâmetro, EstFluOperando, é o nome da nova classe de feições que
queremos criar. E assim, uma vez feito isso, temos uma nova classe de feições e podemos
executar a ferramenta Delete para limpar nossa camada de feições temporária. E isso é tudo
o que precisamos fazer neste script.
Exercício 4
Abaixo está uma abordagem possível para o Exercício 4. Observe que o nome da
cidade é armazenado perto do topo do script em uma variável para que possa ser testado
com outros valores. A expressão SQL requer um pouco de trabalho para ser criar devido à
consulta de string usando dois tipos diferentes de aspas.
# Seleciona postos Flu para uma determinada cidade alvo e os exporta
# para uma nova feature class
import arcpy
cidadeAlvo = "Linhares" # Nome da cidade alvo
arcpy.env.workspace = "C:\\SEA5923\\Dados\\BD.gdb"
postosFlu = "EstacoesFlu" # Nome da feature class dos postos
cidades = "Cidades" # Name da feature class das cidades
# Criando a expressão SQL para a consulta em relação a cidade alvo
expressaoSQL = '"NOME" = ' + "'" + cidadeAlvo + "'"
# cria a feature layers para as cidades e postos
arcpy.MakeFeatureLayer_management(cidades, "cidadesLayer", expressaoSQL)
arcpy.MakeFeatureLayer_management(postosFlu, "postosFluLayer")
# Seleciona todos os postos dentro da cidade alvo
arcpy.SelectLayerByLocation_management("postosFluLayer", "CONTAINED_BY",
"cidadesLayer")
# Copia as feições para uma nova classe de feições
arcpy.CopyFeatures_management("postosFluLayer", "PostosFlu_"+cidadeAlvo)
arcpy.Delete_management("postosFluLayer")
arcpy.Delete_management("cidadesLayer")
Explicação:
E esta solução terá muitos elementos que foram usados nos exercícios 2 e 3. Esses
padrões devem começar a parecer familiares para você.
Iniciamos importando o módulo arcpy e, em seguida, configuramos uma variável para
representar a cidade na qual deseja-se selecionar os postos. Faremos uma consulta de
atributos para esta cidade, e então seguimos com uma consulta espacial para pegar os
postos que estão dentro da cidade selecionada. Colocar a variável da cidade alvo no topo
dessa forma nos permite mudar a cidade para que possamos testar com valores diferentes
sem procurar no código e descobrir onde ela está.
Configuramos o local de trabalho, que será o arquivo geodatabase. Essa foi uma
técnica que também está na solução do Exercício 3, o que é conveniente, porque vou
trabalhar com várias classes de feições aqui. Segue-se configurando algumas variáveis que
representam os nomes dessas classes de feições. Isso não é necessário. Eu poderia
simplesmente conectar essas strings diretamente nas funções, mas desta forma o código
fica mais fácil de ser interpretado.
158
Assim, quando trabalhamos com muitos conjuntos de dados, é preferível configurar
tudo no começo apenas para poder ver exatamente com o que se está trabalhando. Mas
isso é opcional.
Para o restante do código, seria interessante utilizar os blocos try, accept e finally. Para
simplificar, deixei isso de fora, embora, para a qualidade do código, você seja solicitado a
incluí-los nos locais apropriados nas submissões de seus projetos.
Passamos a configuração da string de consulta SQL para obter apenas a cidade alvo,
no exemplo “Linhares”. Então, estou fazendo essa consulta de atributo aqui, semelhante ao
que foi feito no exercício 2. Estou consultando o campo de nome da cidade. O nome do
campo precisa ser colocado entre aspas duplas na string. Então, estou colocando a primeira
parte da string entre aspas simples.
O nome da cidade deve estar entre aspas simples na consulta. Então eu tenho que
fazer uso da concatenação de string aqui e colocar cada uma dessas aspas simples entre
aspas duplas, para então, colocar tudo junto, e assim ter essa string de consulta completa.
E uma vez que eu a tenha, pode-se com isso criar uma camada da cidade alvo.
E agora este padrão de criar a camada de feição e passar os parâmetros deve ser
familiar para você. O primeiro parâmetro é o nome da classe de feições que estamos usando.
E lembre-se configuramos uma variável para isso. O segundo parâmetro é o nome que eu
quero dar a essa camada de feições ao longo deste script. Vou chamá-la de camada de
cidadesLayer.
E então o terceiro parâmetro é a expressão de consulta SQL opcional, e é o que
reduzirá as cidades para ser apenas uma cidade, neste caso. Segue-se fazendo uma
camada de feições de todas os postos. Neste ponto só passamos dois parâmetros porque
queremos todos os postos. Então, não passamos nenhum tipo de string de consulta aqui.
Então os dois parâmetros são a variável que eu configurei previamente que aponta
para a classe de feições EstacoesFlu, e o nome que eu quero dar a essa nova camada de
feição no script, que chamaremos de postosFlulayer.
Com todos esses elementos, agora podemos fazer uma camada de seleção por
localização para obter apenas os postos que estão dentro da cidade selecionada. Para isso
criamos a camada com o tipo de relacionamento espacial que desejamos, que é está contido,
como vimos em exercícios prévios.
Como estamos trabalhando com a camada de cidades para fazer a seleção, ela será o
terceiro parâmetro. Depois de fazer essa seleção, posso copiar essas feições selecionadas
em uma nova classe de feições. E assim como vimos no exercício 3, usando a ferramenta
Copy Features, criamos a nova classe de feições cujo nome advém da concatenação de
“PostosFlu_” e o valor da variável cidadeAlvo.
No final do código, provavelmente dentro de um bloco Finally ou em algum lugar no
final, devemos excluir as camadas de feição para limpá-las da memória. E neste caso, temos
duas camadas de feições para limpar.
Isto é tudo o que é necessário para concluir este exercício.
159
Etapa 4
Exercício 1
Aqui está uma maneira de abordar o Exercício 1 da etapa 4 com comentários para
explicar o que está acontecendo. Se você tiver uma solução diferente ou mais eficiente,
compartilhe.
# Lê as coordenadas de um arquivo texto e cria um polígono
import arcpy
import csv
shapefile = "C:\\SEA5923\\Dados\\Estado_Misterioso.shp"
caminhoArquivo = "C:\\SEA5923\\Dados\\estado_misterioso.csv"
refEspacial = arcpy.Describe(shapefile).spatialReference
# Abre o arquivo e lê a primeira(e somente) linha
arquivo = open(caminhoArquivo, "r")
leitorCSV = csv.reader(arquivo)
# Este objeto Array armanezará no sentido horário os objetos de pontos
# para criar o polígono
poligonoArray = arcpy.Array()
# Percorre cada par de coordenadas e cria um objeto de ponto
for coordenadas in leitorCSV:
# Cria o ponto, atribuindo os valores de X e Y da lista
ponto = arcpy.Point(coordenadas[0],coordenadas[1])
# Adiciona o ponto criado ao Array
poligonoArray.add(ponto)
# Cria o polígono a partir do array
poligono = arcpy.Polygon(poligonoArray, refEspacial)
# Cria um cursor de inserção e adiciona o polígono a uma nova linha
with arcpy.da.InsertCursor(shapefile, ("SHAPE@",)) as cursor:
cursor.insertRow((poligono,))
Explicação:
O primeiro detalhe a ser observado neste exercício é que olhando para o arquivo de
pontos temos que a primeira coordenada nesta lista e a última são as mesmas, indicando
que será um polígono. Esta é uma lista bastante básica. Não há um cabeçalho. Então, vamos
apenas tratar isso como se fosse um arquivo csv com duas colunas e nenhum cabeçalho.
Para fazer isso, vamos usar o arcpy, que importamos no início e o módulo csv para o
Python. Também configuramos algumas variáveis referenciando os arquivos com os quais
vamos trabalhar neste script. Então, estamos trabalhando com o shapefile do estado
misterioso que foi fornecido para você.
Este shapefile tem um sistema de coordenadas, que é coordenadas geográficas
SAD69. No entanto, não há nenhum polígono dentro deste shapefile ainda. Você adicionará
isso no final. Depois fazemos referência ao caminho para o arquivo de texto que contém
todos os pontos de coordenadas.
Usamos então a propriedade referenceSpatial do método Describe para detectar a
referência espacial do arquivo shapefile. Usaremos isso mais tarde quando começamos a
criar as geometrias. Esse padrão de usar o método describe e depois obter a propriedade
de referência espacial deve ser familiar para você a partir do seu trabalho na etapa 2.
Seguimos, abrindo o arquivo de texto que possui os pontos. Então o primeiro parâmetro
com o método open é caminho, que criamos para a variável caminhoArquivo. E então o
160
segundo parâmetro é r entre aspas. E isso significa que estamos abrindo no modo de leitura.
Nós apenas vamos ler este arquivo. Nós não vamos escrever nada nele.
Passamos esse arquivo para o construtor leitorCSV para que possamos criar esse
objeto que nos permitirá percorrer todas as linhas do arquivo de maneira fácil. Antes de
começarmos a fazer isso, criamos um objeto de array vazio.
Sabemos que neste caso vamos apenas criar uma geometria. Vai ser um polígono com
um array. Então não há problema em criar esse array antes de iniciarmos o loop. E nós
realmente não queremos criá-lo em loop porque estaríamos criando múltiplos arrays, e só
precisamos de um deles neste caso.
Começamos a percorrer as linhas no arquivo com o loop for. Cada linha será
representada aqui por uma variável chamada coordenadas. E assim, podemos criar um
objeto de ponto. E quando você cria um ponto, você precisa de pelo menos a coordenada
de longitude, que é o valor de X, e a latitude, que é Y.
Voltando ao nosso arquivo, você verá que na primeira coluna ou coluna 0, essa é a
longitude. Então nós temos as coordenadas 0 no nosso código. E então a próxima
coordenada é a latitude ou a coordenada y. Isso é na coluna com o índice 1. Então, usamos
coordenadas 1 para y.
Quando tivermos esse ponto, podemos adicioná-lo ao array. Continuamos fazendo
isso, percorrendo o arquivo até adicionarmos ponto após ponto dentro do array e chegamos
ao fim.
Agora, saímos do loop. Observe isso porque não está recuado. E vamos pegar o array
que fizemos e criar um objeto polígono dele. Então nós usamos arcpy.Polygon. E os
parÂmetros que passamos são o próprio array, e depois a referência espacial para essa
geometria, que recuperamos no início do script.
Então, temos o polígono todo configurado, mas ainda não o adicionamos ao shapefile.
E para fazer isso, vamos usar um InsertCursor. Nesse caso, usamos apenas a instrução
simples with para criar o InsertCursor.
O InsertCursor precisa de alguns parâmetros para começar. Ele precisa do caminho
para o arquivo que vamos modificar e é representado pela variável shapefile. Lembre-se que
criamos isso lá no início.
E então há uma tupla de campos que vamos modificar. No nosso caso, só vamos
modificar a geometria. Nós não vamos modificar nenhum atributo, então a maneira que nós
fornecemos esta tupla é que ela tem apenas um item chamado shape com o sinal @, e então
uma vírgula. Uma tupla de um item acaba com uma vírgula como essa dentro dos
parênteses.
E então inserimos a linha. E insere-se apenas a geometria do polígono e nada mais
como descrito. Quando isso for feito, poderemos entrar no ArcMap e verificar se realmente
temos um polígono dentro desse shapefile.
Exercício 2
Este exercício prático é um pouco mais complicado do que os exercícios anteriores. Se
você não conseguiu codificar uma solução, estude cuidadosamente a solução a seguir e
verifique se sabe o objetivo de cada linha do código.
161
O código abaixo se refere ao "vencedor" e "perdedor" de cada jogo. Lembre-se que no
caso de empate isso realmente se refere à primeira pontuação dada e a segunda pontuação
dada.
# Lê de um arquivo texto (futebol) os placares das partidas e armazena
# o maior número de gols de uma partida para cada time
import csv
indiceVencedor = cabecalho.index("Vencedor")
indiceGolsVencedor = cabecalho.index("GV")
indicePerdedor = cabecalho.index("Perdedor")
indiceGolsPerdedor = cabecalho.index("GP")
162
verificaGols(perdedor, golsPerdedor, maxGolsDicionario)
# Imprimindo os resultados
for chave in maxGolsDicionario:
print (chave + ": " + maxGolsDicionario[chave])
Explicação:
Neste exercício é útil usarmos um dicionário, que é uma maneira de armazenar
informações na memória do computador com base em pares de valores de chave. Portanto,
a chave neste caso será o nome da equipe, e o valor será o número máximo de gols
encontrados para essa equipe conforme lemos o arquivo linha por linha. Agora, esse arquivo
é tratado como um arquivo de valores separados por vírgula, embora o delimitador em nosso
caso seja um espaço. O arquivo tem um cabeçalho, que usaremos para extrair informações.
O cabeçalho é organizado em termos de vencedor, gols do vencedor, perdedor, gols
do perdedor. Embora realmente, existem alguns empates. Então, podemos dizer primeira
pontuação e segunda pontuação em vez de vencedor e perdedor. Para os nossos
propósitos, não importa quem ganhou ou perdeu, porque o número máximo de gols pode ter
ocorrido durante uma perda ou empate.
Portanto, esta solução é um pouco mais complexa do que alguns dos outros exercícios
práticos. Envolve uma função que você pode ver foi declarada logo no início do script, mas
não vamos descrevê-la ainda. Vamos esperar até chegarmos a esse ponto em que
precisamos da lógica que está nessa função. Então, vamos começar a explicar essa solução
onde importamos o módulo CSV do Python.
Agora, não há nada neste script que use geometrias ArcGIS ou ArcPy ou algo assim,
então não precisamos importar o ArcPy. Mas você fará isso no Projeto 4, onde usará uma
combinação das técnicas usadas aqui junto com as geometrias do ArcGIS e realmente
colocará tudo junto.
Inicialmente configuramos uma variável que representa o caminho para o arquivo de
texto. E então abrimos o arquivo. Por padrão, ele abre aqui no modo de leitura. O parâmetro
de leitura não é especificamente fornecido aqui.
A seguir criamos o objeto leitor CSV. Você deve estar familiarizado com isso dos outros
exemplos. A única coisa que é diferente aqui é, como um segundo parâmetro, podemos
especificar o delimitador usando esse tipo de sintaxe-- delimitador igual e, em seguida, um
espaço. Este arquivo tem um cabeçalho. Então vamos ler o cabeçalho e depois descobrir as
posições do índice de todas as colunas no arquivo.
Agora, sabemos que estes estão na ordem de posições 0, 1, 2, 3. Mas escrevê-los
usando o método cabecalho.index, torna o script um pouco mais flexível caso a ordem das
colunas tenha sido modificada por alguém, o que poderia facilmente acontecer se alguém
tivesse aberto anteriormente esse arquivo em um programa de planilha eletrônica e movido
as colunas. Vamos criar um dicionário em branco para acompanhar cada equipe e o número
máximo de gols que elas marcaram. Vamos nos referir a esse dicionário com frequência
enquanto lemos o arquivo.
Começamos um loop que realmente começa a ler o arquivo linha por linha após o
cabeçalho. E retiraos essas quatro informações - basicamente, os nomes das duas equipes
e o número de gols marcados. Agora, quando recebemos um nome de equipe, precisamos
verificá-la em nosso dicionário para ver se o número de gols marcados é maior que o máximo
armazenado. E precisamos fazer essa verificação tanto para o vencedor quanto para o
perdedor - ou, em outras palavras, a primeira equipe e a segunda equipe listadas na linha.
163
Para evitar a repetição do código, esse é um bom caso para uma função. Porque vamos
usar a mesma lógica para ambas as partes. Por que não escrever o código apenas uma vez
em uma função? Então, você verá que estou invocando uma função chamada verificaGols.
E eu passo três parâmetros. Eu passo o nome da equipe, passo o número de gols e o
dicionário.
Nesta função criamos variáveis para esses três parâmetros que eu sei que serão
passadas - a equipe, o número de gols e o dicionário. Executamos uma verificação para ver
se a equipe já possui uma chave no dicionário. Em caso afirmativo, precisamos analisar o
número de gols contra os gols máximos registrados para a equipe e verificar para ver se
esse número máximo de gols precisa ser atualizado.
E se, de fato, o número de gols que estão sendo lidos na linha atual for maior que o
máximo que conhecemos, então, atualizamos o máximo e o configuramos igual ao que
lemos dentro da linha. Se o número de gols na linha atual não for maior que o nosso máximo,
então não queremos fazer nada. Aqui usamos o comando pass, ele é apenas uma palavra-
chave que significa não faça nada.
Agora, se a equipe nunca foi lida antes e não tem uma entrada no dicionário para um
número máximo de gols, então vamos definir a equipe. Nós vamos dar à equipe uma chave
no dicionário, e vamos definir seus gols máximos para o que temos lido agora. Porque neste
caso, só lemos um registro para essa equipe, então o máximo é o próprio valor que lemos.
Então, para finalizar este script, uma vez que tenhamos construído todo o nosso
dicionário, vamos percorrê-lo uma última vez e imprimir cada chave e cada valor. E isso pode
ser feito usando um loop for simples. Nesse caso, a variável chave representa uma chave
no dicionário. Imprimimos essa chave, e imprimimos dois-pontos e um espaço e depois
imprimimos o valor associado para essa chave. Se você quiser extrair um valor de um
dicionário, use colchetes e passe o nome da chave. E é o que estamos fazendo no script.
164