Você está na página 1de 164

Automatização SIG

voltada às aplicações ambientais

PPGSEA EESC USP - 2019


Automatização SIG voltada às aplicações ambientais
SEA 5923

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:

Frederico Fábio Mauad


Possui graduação em Engenharia Agrícola (1990), Especialização em Projeto e
Construção de Pequenas Centrais Hidrelétricas - Eletrobrás/UNIFEI, Mestrado em
Engenharia Mecânica- Energia pela Universidade Federal de Itajubá (1995), PDEE Junto
ao Instituto Superior Técnico - Lisboa 1998 e doutorado em Planejamento de Sistemas
Energéticos pela Universidade Estadual de Campinas (2000). Livre-Docente pela
Universidade de São Paulo na área de conhecimento de planejamento de sistemas
hidroenergéticos (2013). Atualmente é Professor Associado da Universidade de São Paulo.
Membro do Comitê Cientifíco do Simpósio da ABRH a partir de 2005 - atual e do Simpósio
do ENES a partir de 2007. Coordenador de Projetos de P&D com o setor Elétrico (ANEEL),
CNPq, FAPESP, FINEP, FEHIDRO e CAPES. Tem experiência na área de Engenharia
Civil, com ênfase em Hidrologia, atuando principalmente nos seguintes temas: Estudo de
Assoreamento de Grandes Reservatórios, Hidrometria Aplicada, Equipamentos para
Análise Quantitativa, Qualitativa e Sedimentometrica, Planejamento e Gerenciamento de
Recursos Hídricos, Aporte de Sedimentos, Recursos Hídricos (Quantitativo e Qualitativo),
Simulação Computacional e Usos Múltiplos da Água.

Cláudio Bielenki Junior


Graduado em Engenharia Cartográfica pela Universidade Federal do Rio Grande do Sul
(2002), Especialista em Geoprocessamento pela Universidade Federal de São Carlos
(2007). Mestre em Engenharia de Transportes pela Escola de Engenharia de São Carlos
da USP (2008). Doutor em Ciências da Engenharia Ambiental na EESC USP (2018).
Desde 2003 é especialista em geoprocessamento da Agência Nacional de Águas.
Atualmente integra a equipe de pesquisadores do Departamento de Hidrobiologia da
UFSCar. Possui experiência na área de Geociências, com ênfase em Geoprocessamento,
Geodésia Geométrica e Espacial, atuando principalmente nos seguintes temas: Recursos
Hídricos, sensoriamento remoto, geoprocessamento, cartografia. Adicionalmente atua na
área de desenvolvimento e otimização de sistemas geo e modelagem hidrológica.
Adaptado por Cláudio Bielenki Jr. do material do Instituto de Educação Eletrônica John A. Dutton,
Faculdade de Ciências Minerais e Terrestres da Penn State University
Quinn, S.; Detwiler, J.; Hardsty, F.; O’Brien, J.
GIS programming and software development. 2018.

Agosto, 2019
Este material está dividido em 4 etapas:

Etapa 1: Introdução à modelagem SIG e Python


A etapa 1 começa explicando como a automação pode tornar o trabalho de um analista
de SIG mais fácil, rápido e preciso. A primeira metade apresenta algumas das ferramentas
de análise SIG disponíveis no ArcGIS e como acessá-las em um contexto não-Python,
especificamente as janelas de diálogos do ArcToolbox, a janela do Python e a interface do
ModelBuilder. No ModelBuilder, você aprenderá como as ferramentas individuais podem ser
“encadeadas” em uma ordem designada para executar tarefas de análise complexas.
A segunda parte apresenta-se a linguagem de script Python, o ambiente de
desenvolvimento PythonWin e a programação orientada a objetos em geral. A lição é
concluída com alguns exemplos simples de scripts, projetados para mostrar como o Python
se conecta ao ArcGIS e como você pode escrever um script Python usando as mesmas
ferramentas que se acessa no ArcToolbox.
Esboço da etapa 1:
• A necessidade de automação SIG
• Explorando uma caixa de ferramentas
• Ambientes para acessar ferramentas
o Executando uma ferramenta do ArcToolbox pela sua caixa de diálogo
o Modelagem com ferramentas
• Por que aprender ModelBuilder?
o Abrindo e explorando ModelBuilder
o Parâmetros do modelo
o Conceitos avançados de geoprocessamento e ModelBuilder
o Executar uma ferramenta na janela da linha de comando
• Apresentando o Python
o O que é o Python?
o Instalando o Python e o PythonWin
o Explorando o PythonWin
• Começando a programação com Python
o Trabalhando com variáveis
o Objetos e programação orientada a objetos
o Classes
o Herança
o Sintaxe Python
• Exemplos introdutórios do Python
o Exemplo: Imprimindo a referência espacial de uma classe de feições
o Exemplo: Realizando álgebra de mapas em uma imagem raster
o Exemplo: Criando Buffers
• Fazendo uma ferramenta de script
• Projeto 1: Modelagem de zonas de precipitação (exercício ModelBuilder)
• Tarefa 1: Criando contornos para um MNT (exercício em Python)

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

Etapa 3: Acesso e manipulação de dados SIG com Python


Uma grande vantagem do script é a capacidade de ler, atualizar e adicionar dados
automaticamente. Na etapa 3 mostra-se como acessar dados vetoriais e rasterizados no
ArcGIS usando o Python. Os dados são recuperados por meio de consultas espaciais e de
atributos. A lição mostra como subconjuntos de registros podem ser atualizados com base
em determinados critérios (como por meio de uma operação de “localizar e substituir”). A
ênfase é tratamento de dados vetoriais trabalhando com as tabelas de atributos, embora
ferramentas para trabalhar com dados raster também sejam discutidas.
Esboço da etapa 3:
• Armazenamento e recuperação de dados no ArcGIS
• Lendo dados de atributos de vetores
o Acessando s campos da tabela de atributo
o Lendo registros
o Recuperando registros usando uma consulta de atributo
o Recuperando registros usando uma consulta espacial
• Escrevendo dados de atributo de vetores
o Atualizando registros existentes
o Inserindo novos registros
• Trabalhando com rasters
• Projeto 3

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

No final desta etapa, você deve:


• Ser capaz de criar fluxos de trabalho automatizados no ArcGIS ModelBuilder;
• Estar familiarizado com o ambiente de desenvolvimento do Python;
• Conhecer alguns dos tipos de dados básicos mais importantes do Python e
como usar variáveis em scripts Python;
• Estar familiarizado com os conceitos básicos de programação orientada a
objetos (por exemplo, classes e herança);
• Ser capaz de usar funções de ferramentas do Arcpy para realizar tarefas
básicas de análise espacial; e
• Saber como criar uma ferramenta de script simples e passar um parâmetro
para um script.

A necessidade de automação SIG


Um sistema de informação geográfica (SIG) pode manipular e analisar conjuntos de
dados espaciais com o objetivo de resolver problemas geográficos. Os analistas de SIG
realizam todos os tipos de operações em dados para torná-lo útil para resolver um problema
localizado. Isso inclui recorte, reprojeção, buffer, mesclagem, mosaicagem, extração de
subconjuntos dos dados e centenas de outras operações. No software ArcGIS utilizado neste
curso, essas operações são conhecidas como geoprocessamento e são realizadas por meio
de ferramentas.
Uma análise SIG bem-sucedida requer a seleção das ferramentas mais apropriadas
para operar sobre os seus dados. O ArcGIS usa uma metáfora de caixa de ferramentas para
organizar seu conjunto de ferramentas. Você escolhe as ferramentas necessárias e as
executa na ordem correta para ter um resultado esperado.
Suponha que você seja responsável por selecionar locais para um aterro sanitário.
Você pode usar uma ferramenta para selecionar lotes de terra ao longo de uma via de
acesso, outra ferramenta para selecionar parcelas não menores que uma determinada área
e outras ferramentas para outros critérios de seleção, como distância a mananciais, tipo de
solo entre outros. Se esse processo de seleção fosse limitado a uma única área,
provavelmente faria sentido executar o trabalho manualmente.
No entanto, vamos supor que você seja responsável por realizar a mesma análise para
várias cidades. Como esse cenário envolve a execução da mesma sequência de
ferramentas para várias áreas, é uma tarefa que se presta bem à automação. Existem vários
benefícios importantes para automatizar tarefas como esta:

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.

Explorando uma caixa de ferramentas


O software ArcGIS que você utiliza neste curso contém centenas de ferramentas que
você pode usar para manipular e analisar dados SIG. Antes que o ArcGIS tivesse uma
interface gráfica de usuário (GUI), as pessoas acessavam essas ferramentas digitando
comandos. Hoje em dia, você pode apontar e clicar em seu caminho por toda uma hierarquia
de caixas de ferramentas usando o ArcCatalog ou a janela Catálogo no ArcMap.
Embora você possa tê-los visto antes, vamos dar uma olhada rápida nas caixas de
ferramentas:
• Abra o ArcMap.
• Se a janela Catálogo não estiver visível, clique no menu Windows e, em
seguida, clique em Catalog. Se você passar o mouse sobre ou clicar no item Catálogo
no lado direito da tela, poderá fazer com que a janela Catálogo apareça. Opcionalmente,
você pode "fixá-lo" para que ele não se esconda.
• No Catálogo, expanda os nós Toolboxes> System Toolboxes e continue
expandindo as caixas de ferramentas de sua escolha até ver algumas das ferramentas
disponíveis. Observe que eles estão organizados em caixas de ferramentas e conjuntos
de ferramentas. Às vezes, é mais rápido usar a janela Search (Geoprocessing> Search
For Tools) para encontrar a ferramenta de que você precisa, em vez de navegar nesta
árvore.
• Vamos examinar uma ferramenta. Expanda AnalisysTools> Proximity>
Buffer e clique duas vezes na ferramenta Buffer para abri-la.
• Preste atenção aos componentes que compõem a interface do usuário.
Especificamente, você está olhando para uma caixa de diálogo com muitos campos.
Cada ferramenta de geoprocessamento exige parâmetros de entradas e saídas. Estes
são indicados pelos pontos verdes. Eles representam a quantidade mínima de
informações que você precisa fornecer para executar uma ferramenta. Para a ferramenta
Buffer, é necessário fornecer um local que indica o arquivo de entrada (as feições que

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.

Ambientes para acessar ferramentas


Você pode acessar as ferramentas de geoprocessamento do ArcGIS de várias
maneiras diferentes:
• Às vezes, você só precisa executar uma ferramenta uma única vez ou testar
uma ferramenta e seus parâmetros. Neste caso, você pode abrir a ferramenta

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.

Executando uma ferramenta a partir de sua caixa de diálogo


Vamos começar abrindo uma ferramenta a partir da janela Catálogo e executando-a
usando sua interface gráfica do usuário (GUI).
• Se por acaso você ainda tiver a ferramenta Buffer aberta da seção anterior,
feche-a por enquanto para adicionar alguns dados.
• Crie uma pasta na sua máquina em C:\SEA5923. Se você usar um caminho
diferente, substitua seu caminho nos exemplos a seguir.
• Extraia os dados de Dados.zip para sua nova pasta, de modo que os dados
fiquem no caminho C:\SEA5923\Dados\. Esta pasta contém uma variedade de conjuntos
de dados que você usará ao longo da lição.
• Abra o ArcMap e crie um novo mapa.

• 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.

Captura da tela Results mostrando a ferramenta Buffer e todas as mensagens.

Modelando com ferramentas


Quando você trabalha com geoprocessamento, muitas vezes você vai querer usar a
saída de uma ferramenta como entrada para outra ferramenta. Por exemplo, suponha que
você queira encontrar todos os hidrantes a menos de 200 metros de um prédio. Você
realizaria primeiro o buffer de 200 metros e, em seguida, usaria o buffer de saída como uma
restrição espacial para selecionar hidrantes. A saída da ferramenta Buffer seria usada como
uma entrada para a ferramenta Select by Location.

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.

Por que aprender ModelBuilder?


ModelBuilder é a interface gráfica da ESRI para fazer modelos. Você pode arrastar e
soltar ferramentas da janela Catálogo para o modelo e “conectá-las”, especificando a ordem
na qual elas devem ser executadas.
Embora este seja basicamente um curso sobre scripts, passaremos algum tempo no
ModelBuilder durante a primeira lição por dois motivos:
O ModelBuilder é um ambiente agradável para explorar as ferramentas do ArcGIS,
aprender como as entradas e saídas da ferramenta são usadas e entender visualmente
como a modelagem do SIG funciona. Quando você começar a usar o Python, você não terá
a mesma assistência visual para ver como as ferramentas que você está usando estão
conectadas, mas você ainda pode querer desenhar seu modelo em um quadro de forma
semelhante ao que você viu no ModelBuilder.
ModelBuilder pode frequentemente reduzir a quantidade de codificação Python que
você precisa fazer. Se o seu problema de SIG não requer uma lógica condicional e iterativa
avançada, você poderá executar seu trabalho no ModelBuilder sem escrever um script.
ModelBuilder também permite que você exporte qualquer modelo para código Python, então
se você ficar preso implementando algumas ferramentas dentro de um script, pode ser útil
criar um modelo de trabalho simples em ModelBuilder e exportá-lo para Python para ver
como o ArcGIS construiria o código. (A exportação de um modelo complexo não é
recomendada para iniciantes devido à quantidade detalhada de código que o ModelBuilder
tende a criar ao exportar o Python).

Abrindo e explorando ModelBuilder


Vamos praticar um pouco com o ModelBuilder para resolver um cenário real. Suponha
que você esteja trabalhando em um problema de seleção de locais (áreas com aptidão a
determinado uso, por exemplo), no qual você precisa selecionar todas as áreas que caem
dentro de 5 km de uma rodovia principal e 5 km de uma cidade. A área selecionada não
pode ficar no oceano ou fora de um limite definido. Resolver o problema exige que você faça
buffers em torno das estradas e das cidades, cruze os buffers e, em seguida, limite-os ao
contorno determinado. Em vez de abrir manualmente a ferramenta Buffer duas vezes,

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:

A aparência do modelo seguindo o passo acima.


• A etapa final é recortar os buffers interceptados no contorno dos Estados
Unidos. Isso impede que qualquer área selecionada caia fora do limite. Na janela

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.

O modelo completo com a ferramenta de clipe incluída.


• Clique duas vezes no elemento de saída final (chamado "Área de Aptidão" na
imagem acima) e defina o caminho para C:\SEA5923\Dados\AreaAptidao.shp.
• Clique com o botão direito do mouse em "Área de Aptidão" e clique em Add to
display.
• Salve seu modelo novamente.

• Teste o modelo clicando no botão Executar. . O ModelBuilder também


fornece uma indicação visual de qual ferramenta está sendo executada, tornando a
ferramenta em execução vermelha.
• Quando o modelo terminar de rodar (pode demorar um pouco), examine a
saída no ArcMap. Amplie para verificar se o Clip funcionou nas áreas costeiras. A saída
deve ser semelhante a isso.

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.

Execução de modelo sem parâmetros

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:

A interface do modelo, ou diálogo da ferramenta, para o modelo "Localizar áreas de


aptidão com parâmetros"
• As pessoas que executam esse modelo poderão navegar em quaisquer
conjuntos de dados de cidades, rodovias e limites e poderão controlar a distância do
buffer. Os pontos verdes indicam parâmetros que devem ser fornecidos com valores
válidos antes que o modelo possa ser executado.

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.

Conceitos avançados de geoprocessamento e ModelBuilder


Até agora você já teve alguma prática com o ModelBuilder e está pronto para começar
a usar o Python. Esta parte da lição contém algum material avançado que você pode ler
sobre o ModelBuilder. Isso é particularmente útil se você faz uso do ModelBuilder com
frequência no seu trabalho. Alguns dos itens são comuns à estrutura de geoprocessamento
do ArcGIS, o que significa que eles também se aplicam ao escrever scripts Python com o
ArcGIS.
Gerenciando dados intermediários
A análise em SIG às vezes é extensa confusa. A maioria das ferramentas que você
executa produz um conjunto de dados de saída e, ao encadear várias ferramentas, esses
conjuntos de dados começam a se acumular no disco. Mesmo que você seja diligente em
nomear intuitivamente seus conjuntos de dados, é fácil acabar com uma pasta cheia de
conjuntos de dados com nomes como buffers1, clippedbuffers1,
intersectedandclippedbuffers1, raster2reclassificados, etc.
Na maioria dos casos, você está preocupado apenas com o conjunto de dados de saída
final. Os dados intermediários são apenas temporários; você só precisa mantê-lo durante o
tempo necessário para executar o modelo e, depois, ele pode ser excluído.
O ModelBuilder pode gerenciar seus dados intermediários para você, colocando-os em
um diretório temporário chamado de scratch workspace (área de trabalho de rascunho). Por
padrão, a área de trabalho de rascunho é o diretório temporário de seu sistema operacional,
mas você pode configurá-lo para existir em outro local.
Você pode forçar os dados a entrarem na área de trabalho de rascunho usando a
variável %SCRATCHWORKSPACE% no caminho. Por
exemplo:%SCRATCHWORKSPACE%\myOutput.shp
Você também pode marcar qualquer elemento no ModelBuilder como Intermediário e
ele será excluído depois que o modelo for executado. Por padrão, todos os dados derivados
são intermediários.
Os tópicos a seguir da ajuda da ESRI entram em mais detalhes sobre dados
intermediários e são importantes para entender quando você trabalha com o framework de
geoprocessamento. Eu sugiro lê-los uma vez agora e retornar a eles ocasionalmente durante

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.

Introduzindo o Python usando a janela do Python no ArcGIS


A melhor maneira de introduzir o Python pode ser olhar um pouco de código. Vamos
pegar a ferramenta Buffer que você executou recentemente na GUI do ArcToolbox e
executá-la na janela de Comandos Python do ArcGIS. Esta janela permite que você digite
uma simples série de comandos Python sem escrever scripts completos. A janela do Python
é uma ótima maneira de ter um primeiro contato com o Python.
Desta vez, faremos buffers de 10 Km ao redor das cidades.
• Abra o ArcMap para um novo mapa.
• Adicione o conjunto de dados Sedes_Municipais.shp do diretório de dados.

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.

A janela interativa no PythonWin


Para realmente escrever um novo script, clique em File> New e escolha Python Script.
Observe uma página em branco se abre que parece muito com o Bloco de Notas. No entanto,
o interessante dessa interface é que o código é codificado por cores e a fonte padrão,
Courier, é aquela normalmente usada pelos programadores. O espaçamento e o recuo, que
são importantes no Python, também são fáceis de acompanhar nessa interface.

A barra de ferramentas Standard

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.

Trabalhando com variáveis


É hora de praticar um pouco com alguns conceitos de programação iniciais que
ajudarão você a escrever scripts simples em Python até o final da Aula 1. Vamos começar
examinando as variáveis.
Lembre-se da sua primeira aula introdutória de álgebra, onde você aprendeu que um
caractere poderia representar qualquer número, como na declaração x + 3. Esta pode ter
sido sua primeira exposição a variáveis. Na ciência da computação, as variáveis
representam valores ou objetos que você deseja que o computador armazene em sua
memória para uso posterior no programa.
Variáveis são frequentemente usadas para representar não apenas números, mas
também valores de texto e “booleanos” ('true' ou 'false'). Uma variável pode ser usada para
armazenar uma entrada do usuário do programa, para armazenar valores retornados de
outro programa, para representar valores constantes e assim por diante.
Variáveis tornam seu código legível e flexível. Se você codificar seus valores, o que
significa que você sempre usa o valor literal, seu código é útil somente em um cenário
específico. Você pode alterar manualmente os valores em seu código para ajustar-se a um
cenário diferente, mas isso é entediante e expõe a um risco maior de cometer um erro
(suponha que você tenha se esquecido de alterar algum valor). As variáveis, por outro lado,
permitem que seu código seja útil em muitos cenários e sejam fáceis de parametrizar, o que
significa que você pode permitir que os usuários alterem os seus valores para o que
precisarem.
Para ver algumas variáveis em ação, abra o PythonWin e digite isso na Janela
Interativa:
>>> x = 2

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.

Objetos e programação orientada a objetos


As variáveis numéricas e de string com as quais trabalhamos anteriormente
representam tipos de dados que são construídos no Python. As variáveis também podem
representar outras coisas, como conjuntos de dados SIG, tabelas, linhas e o geoprocessador
que vimos anteriormente que podem executar ferramentas. Todas essas coisas são objetos
que você usa quando trabalha com o ArcGIS em Python.
Em Python, tudo é um objeto. Todos os objetos possuem:
• Um ID único ou localização na memória do computador
• Um conjunto de propriedades que descrevem o objeto
• Um conjunto de métodos ou coisas que o objeto pode fazer
Uma maneira de entender objetos é comparar a execução de uma operação em uma
linguagem procedural (como FORTRAN) para executar a mesma operação em uma
linguagem orientada a objetos. Vamos fingir que estamos escrevendo um programa para
fazer um sanduíche de manteiga de amendoim e geleia. Se fôssemos escrever o programa
em uma linguagem procedural, fluiria algo assim:
• Vá até a geladeira e pegue a geleia e o pão.
• Vá até o armário e pegue a manteiga de amendoim.
• Retire duas fatias de pão.
• Abra os frascos.
• Pegue uma faca.

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.

Exemplo: Imprimindo a referência espacial de uma classe de


feições
Este primeiro script de exemplo retorna a referência espacial (sistema de coordenadas)
de uma classe de feições armazenada em um geodatabase:
1 # Abre uma feature class de um geodatabase e retorna a sua
2 # referência espacial
3
4 import arcpy
5
6 featureClass = "C:/SEA5923/Dados/BaseDados.gdb/Limite"
7
8 # O comando Describe aponta para as propriedades da fc
9 desc = arcpy.Describe(featureClass)

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.

Exemplo: Realizando álgebra de mapas com um raster


Aqui está outro script simples que localiza todas as células acima de 750 metros em
um MDT e que codifica todas essas células como 1. Os valores restantes são codificados

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.

1 # Este script usa algebra de mapa para encontrar valores


2 # em um raster maiores que 750 metros
3
4 import arcpy
5 from arcpy.sa import *
6
7 # Especifica o dado raster de entrada
8 rasterEntrada = "C:/SEA5923/Dados/MDE_500m.tiff"
9 elevacaoCorte = 750
10
11 # Realiza a algebra de mapa e salva o resultado
12 rasterSaida = Raster(rasterEntrada) > elevacaoCorte
13 rasterSaida.save("C:/SEA5923/Dados/MDE_Alt750")
Comece examinando esse script e tentando descobrir o máximo que puder com base
no que você lembra dos scripts anteriores que viu.
Os principais pontos a serem lembrados neste script são:
• rasterEntrada começa como uma string, mas depois é usado para criar um
objeto Raster quando você executa Raster(rasterEntrada). Um objeto Raster é um objeto
especial usado para trabalhar com conjuntos de dados tipo imagem ou modelos
numéricos no ArcGIS. Ele não está disponível em nenhum script Python: você pode usá-
lo somente se importar o módulo arcpy na parte superior do script.
• elevacaoCorte é uma variável numérica que você declara no início do seu script
e depois usa quando você cria a expressão de álgebra do mapa para sua rasterSaida.
• A expressão rasterSaida = Raster (rasterEntrada)> elevacaoCorte está
dizendo, em termos simples, "Crie uma nova imagem e chame-a de rasterSaida. Faça
isso tomando todas as células do conjunto de dados raster no caminho de rasterEntrada
que são maiores que o número I atribuído à variável elevacaoCorte".
• rasterSaida também é um objeto Raster, mas você deve chamar o método
rasterSaida.save() para torná-lo permanente no disco. O método save() recebe um
argumento, que é o caminho para o qual você deseja salvar.
• Agora tente executar o script usando o modelo de elevação digital (DEM)
MDE_500m.tiff de sua pasta de dados. Se não funcionar na primeira vez, verifique se:

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.

Exemplo: Criando buffers


Pense no exemplo anterior em que você executou alguma álgebra de mapa em um
modelo de elevação. Se você quisesse alterar o valor de sua elevação de corte para 1000
em vez de 750, você teria que abrir o script em si e alterar o valor da variável elevacaoCorte
diretamente no código.
Este terceiro exemplo é um pouco diferente. Em vez de codificar os valores necessários
para a ferramenta (em outras palavras, incluir literalmente os valores no script), usaremos
algumas variáveis ou parâmetros de entrada do usuário. Isso permite que as pessoas
experimentem valores diferentes no script sem alterar o próprio código. Assim como no
ModelBuilder, os parâmetros disponibilizam seu script para um público mais amplo.
O exemplo simples abaixo apenas executa a ferramenta Buffer, mas permite que o
usuário insira o caminho dos conjuntos de dados de entrada e saída, bem como a distância
do buffer. Os parâmetros fornecidos pelo usuário entram no script com o método
arcpy.GetParameterAsText().
Examine cuidadosamente o script abaixo, mas não tente executá-lo ainda. Você fará
isso na próxima parte da lição.

1 # Este script executa a ferramenta Buffer. O usuário indica


2 # os caminhos de entrada e saída, e a distância do buffer.
3
4 import arcpy
5 arcpy.env.overwriteOutput = True

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.

Fazendo uma ferramenta de script


As variáveis de entrada do usuário que você recupera por meio do comando
GetParameterAsText() facilitam muito a conversão de seu script em uma ferramenta no
ArcGIS.
Algumas poucas pessoas sabem como alterar um código Python, outras poucas sabem
executar um script Python e fornecer as variáveis de entrada do script, mas quase todos os
usuários do ArcGIS sabem como abrir o ArcToolbox e executar uma ferramenta. Para
terminar esta lição, vamos pegar o script anterior e transformá-lo em uma ferramenta que
pode ser facilmente executada no ArcGIS.
Antes de começar este exercício, eu recomendo fortemente que você verifique o tópico
de ajuda do ArcGIS Adicionando uma ferramenta de script. Você provavelmente não
entenderá todas as partes deste tópico ainda, mas lhe dará alguma familiaridade com as
ferramentas de script que serão úteis durante o exercício.
Siga estas etapas para criar uma ferramenta de script:
• Copie o código da tarefa "Exemplo: Criando Buffers" em um novo script
PythonWin e salve-o como buffer_user_input.py.

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:

Inserindo informações para sua ferramenta de script.


• Clique em Avançar (Next) e forneça o arquivo de script. Para fazer isso,
clique no ícone da pasta e navegue até o arquivo buffer_user_input.py.
• Clique em Avançar (Next) e examine a caixa de diálogo exibida. É aqui que
você pode especificar os parâmetros do seu script. Os parâmetros são os valores para
os quais você usou arcpy.GetParameterAsText() no seu script, ou seja, entrada, saida e
distanciaBuffer. Você usará essa caixa de diálogo para listar esses parâmetros na
mesma ordem, exceto que você pode fornecer aos parâmetros nomes mais fáceis de
entender.
• Na coluna Display Name que você vê na parte superior deste assistente, clique
na primeira célula vazia e digite “Classe de feições de entrada”.
• Imediatamente à direita, clique na primeira célula vazia na coluna Data Type e
escolha Feature Class. Aqui está uma das grandes vantagens de criar uma ferramenta

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).

Alterando as propriedades de um parâmetro


• Adicione uma terceira propriedade chamada “Distância do buffer”. Escolha
Linear Unit como o tipo de dados. Esse tipo de dados permitirá que o usuário da
ferramenta selecione o valor da distância e as unidades (por exemplo, milhas,
quilômetros, etc.).

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:

Inserindo valores de entrada padrão em um parâmetro


• Clique em Finish e, na janela Catalog, abra sua nova ferramenta de script
clicando duas vezes nela.

Ferramenta completa pronta para rodar


• Experimente a sua ferramenta colocando em buffer qualquer classe de feições
de seu computador. Observe que, uma vez que você fornece a classe de feições de
entrada, um caminho da classe de feições de saída é sugerido para você. Isso ocorre
porque você define especificamente a Classe de Recurso de Saída como um parâmetro
de saída. Além disso, quando a ferramenta estiver concluída, examine a janela
Resultados da mensagem personalizada "Tudo certo!" que você adicionou em seu
código.

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:

Comparação da nossa ferramenta de script com a principal ferramenta de buffer


• Em algum momento, você pode precisar projetar um conjunto de ferramentas
para usuários de SIG iniciantes, onde apenas os parâmetros mais necessários são
expostos. Você também pode fazer isso para impor o controle de qualidade se souber
que alguns dos parâmetros devem sempre ser definidos para determinados padrões e
se deseja evitar o cenário em que um usuário inexperiente (ou um usuário não
autorizado) possa alterar os valores necessários. Uma ferramenta de script simples é
eficaz para simplificar o diálogo da ferramenta dessa maneira.

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.

Projeto 1: Modelagem de zonas de precipitação


Suponha que você esteja trabalhando em um projeto para um Departamento ambiental
e tenha a tarefa de fazer alguns mapas de precipitação para uma determinada região (uma
bacia hidrográfica, por exemplo). Membros do departamento querem ver quais partes desta
região estavam relativamente secas e úmidas no ano de 2018, classificadas em zonas. Tudo
o que você tem é uma série de leituras de estações meteorológicas de precipitação anual
acumulada para 2018 que você obteve para a região de interesse e áreas adjacentes. Este
é um shapefile de pontos chamado Plu_Total_Anual.shp. Está na sua pasta de dados.
Este é um conjunto de dados fictício criado para este projeto. As localizações
correspondem às estações meteorológicas reais. No entanto, as medições são derivadas de
dados aproximados de precipitação de anos anteriores.
Você precisa executar várias tarefas para preparar esses dados para o mapeamento:
• Interpolar uma superfície de precipitação a partir de seus pontos. Isso cria um
conjunto de dados raster com valores estimados de precipitação para toda a sua área de
interesse. Imagine que você já planejou isso, sabendo que vai usar a interpolação de
distância inversa ponderada (IDW). Você também selecionou seus pontos para incluir
algumas áreas ao redor da região de interesse para evitar efeitos de borda na
interpolação.
• Reclassificar a superfície interpolada em uma classificação ordinal de "zonas"
de precipitação que delineiam regiões relativamente secas, médias e úmidas.
• Crie polígonos vetoriais das zonas.
• Recorte os polígonos das zonas de precipitação pelo limite da região de
interesse.

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:

A saída do modelo concluído

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.

Tarefa 1: Script para criar curvas de nível


Este exercício ajudará você a praticar com o Python. Até agora você viu três exemplos
simples de scripts; aqui a sua tarefa é escrever seu próprio script. Esse script criará linhas
de contorno (curvas de nível) de vetor a partir de um conjunto de dados de elevação raster.
Não esqueça que a Ajuda do ArcGIS Desktop pode realmente ser útil se você precisar
descobrir a sintaxe de um comando em particular.
Na pasta de dados está o MNT MDE_Onca.tiff que representa as elevações na região
da bacia hidrográfica do Ribeirão da Onça no município de Itirapina SP. Escreva um script
que use a ferramenta Contour na caixa de ferramentas do Spatial Analyst para criar as
curvas de nível para a região do MNT. O intervalo de contorno deve ser de 20 metros e o
contorno de base deve ser 600. Lembre-se de que as unidades nativas do MMNT são
metros, portanto, não são necessárias conversões de unidades.
A execução do script deve criar imediatamente um shapefile de linhas de contorno no
disco.
Siga estas diretrizes ao escrever o script:
• O objetivo deste exercício é apenas fazer com que você pratique a escrita do
código Python. Portanto, você não é obrigado a usar o arcpy.GetParameterAsText () para
obter os parâmetros de entrada. Vá em frente e codifique os valores (como o nome do
caminho para o conjunto de dados).

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

Mais fundamentos do Python


Até aqui, você aprendeu sobre o ModelBuilder, e isso pode ser suficiente para resolver
muitas das tarefas de SIG que você precisa no seu trabalho. No entanto, por mais útil que
seja o ModelBuilder, você descobrirá que às vezes você precisa do Python para adicionar
inteligência em suas análises de geoprocessamento. Por exemplo, você pode precisar
construir cadeias de consulta complexas ou empregar lógica condicional. Pode ser
necessário ler ou analisar vários tipos de dados de entrada antes de poder enviá-lo para
uma ferramenta como um parâmetro. Ou você pode precisar fazer um loop complexo que,
em algum limite, provavelmente se tornará mais fácil de escrever em Python do que modelar
com o ModelBuilder.
Na etapa 1, você viu seus primeiros scripts Python e foi introduzido ao básico, como
importar módulos, usar arcpy, trabalhar com propriedades e métodos. Nas etapas a seguir,
você aprenderá mais fundamentos da programação Python, como trabalhar com listas,
executar loops, estruturas de decisão if / else, manipular strings e converter variáveis.
Embora isso possa não ser a parte mais interessante do curso, é provavelmente a
seção mais importante para você gastar tempo compreendendo e experimentando por conta
própria, especialmente se você é novo em programação.
A programação é semelhante à prática de esportes: se você dedicar algum tempo para
praticar os fundamentos, terá mais facilidade quando precisar reunir todas as suas
habilidades. Por exemplo, pense nas coisas que você precisa aprender para jogar basquete.
Um jogador de basquete disciplinado pratica dribles, passes, arremessos de longa distância,
tocos, lances livres, defesa e outras habilidades. Se você praticar cada um desses
fundamentos individualmente, você poderá usá-los todos juntos quando for a hora de jogar
um jogo completo.
Aprender uma linguagem de programação é da mesma maneira. Quando confrontado
com um problema, você será forçado a utilizar suas habilidades fundamentais para elaborar
um plano viável. Pode ser necessário incluir um loop em seu programa, armazenar itens em
uma lista ou fazer com que o programa faça uma entre tantas coisas diferentes com base

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.

# Copia todas as classes de feições de uma pasta para outra


import arcpy

try:
arcpy.env.workspace = "C:/SEA5923/Dados"

# Lista as classes de feições da pasta Dados


fcList = arcpy.ListFeatureClasses()

# percorre a lista e copia as fc para a pasta Dados2


for featureClass in fcList:
arcpy.CopyFeatures_management(featureClass, "C:/SEA5923/Dados2/"
+ featureClass)

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)

#Este loop percorre cada linha da tabela de atributos


# e armazena o valor do campo requisitado

for linha in linhas:


nomeCidade = row.getValue(campo)
print (nomeCidade)

No exemplo acima, um cursor de pesquisa denominado “linhas” recupera registros da


tabela. O loop for possibilita executar uma ação em cada registro individual.
Leitura de Ajuda do ArcGIS
Leia o seguinte na Ajuda do ArcGIS Desktop:
http://desktop.arcgis.com/en/arcmap/latest/analyze/python/listing-data.htm

Estruturas de decisão IF - ELSE


Muitos scripts que você escreve precisarão ter lógica condicional que execute um bloco
de código dado uma condição e talvez execute um bloco de código diferente, dada uma
condição diferente. O "if" as instruções "elif" e "else" no Python fornecem essa lógica
condicional. Tente digitar este exemplo na Janela Interativa do PythonWin:
>>> x = 3
>>> if x > 2:
... print ("Maior que dois")

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

# Escolhe uma escola aleatoriamente de uma lista e a imprime


escolas = ["UFSCar", "EESC USP", "UNICEP"]
randomEscolasIndex = random.randrange(0,3)
escolaEscolhida = escolas[randomEscolasIndex]
print (escolaEscolhida)

# dependendo da escola escolhida, imprime o tipo de escola


if escolaEscolhida == "UFSCar":
print ("Universidade Federal")
elif escolaEscolhida == "EESC USP":
print ("Universidade Estadual")
elif escolaEscolhida == "UNICEP":
print ("Universidade Privada")
else:
print ("Este programa apresentou um erro!")
Algumas outras linguagens de programação existem palavras-chave especiais
(comandos) para fazer o mesmo, como switch ou select case. No Python, no entanto,
geralmente é feito apenas com uma longa lista encadeada de "if"s e "elif"s.

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:

# Este script recorta (clip) todos os dados de um diretório


import arcpy

pastaEntrada = "c:\\SEA5923\\Dados\\FC\\"
pastaResultados = "c:\\SEA5923\\FC\\resultados\\"
clipFeature = "c:\\SEA5923\\Dados\\Consorcio_mun.shp"

# Cria a lista das classes de feições no diretório


arcpy.env.workspace = pastaEntrada
listaFC = arcpy.ListFeatureClasses()

# Percorre cada fc da lista e realiza o recorte


for FC in listaFC:

# Escreve o caminho concatenando strings


caminhoSaida = pastaResultados + FC
# Aplica a ferramenta de Clip para a fc
arcpy.Clip_analysis(FC, clipFeature, caminhoSaida)
A concatenação de strings está ocorrendo nesta linha: caminhoSaida =
pastaResultados + FC. A pasta de saída "C:\\SEA5923\\Dados\\FC\\resultados\\" está
recebendo o nome da classe de feição adicionado no final. Se o nome da classe de feição

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.

Colocando tudo junto


Até aqui você aprendeu os conceitos básicos de programação de listas, loops,
estruturas de decisão e manipulação de strings. Você pode se surpreender com o que você
pode fazer apenas com essas habilidades. Nesta seção, praticaremos colocando todos estes
comandos juntos para resolver um desafio.
O cenário que abordaremos é simular um jogo infantil "Hi Ho! Cherry-O" da Hasbro.
Neste simples jogo de azar, o jogador começa com 10 cerejas em uma árvore. Na sua
rodada o jogador gira uma roleta aleatória que informa se o jogador adiciona ou remove
cerejas da árvore.

Tabuleiro do jogo Hi Ho! Cherry-O


Os possíveis resultados da roleta são:
• Remover 1 cereja
• Remover 2 cerejas
• Remover 3 cerejas
• Remover 4 cerejas
• Pássaro visita seu balde de cerejas (Adicione 2 cerejas)

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:

# Simulando o jogo Hi Ho! Cherry-O


import random
valoresRoleta = [-1, -2, -3, -4, 2, 2, 10]
jogadas = 0
cerejasNaArvore = 10
# Realize uma jogada enquanto houver cerejas na árvore
while cerejasNaArvore > 0:
# Rode a roleta
roletaIndex = random.randrange(0, 7)
resultadoRoleta = valoresRoleta[roletaIndex]
# Print o resultado da roleta
print ("Você tirou " + str(resultadoRoleta) + ".")

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.

Solução de problemas e obtenção de ajuda


Se você acha que escrever um código é um processo lento, mistificado e meticuloso,
repleto de todos os tipos de oportunidades para cometer erros, seja bem-vindo ao mundo de
um programador! Talvez para seu desgosto, os programadores passam a maior parte do
tempo procurando e consertando bugs. Os programadores também precisam expandir e
adaptar continuamente suas habilidades para trabalhar com novas linguagens e tecnologias,
o que requer pesquisa, prática e muito tentativa e erro.
Os melhores candidatos para trabalhos de engenharia de software não são aqueles
que listam a maioria das linguagens ou siglas em seus currículos. Em vez disso, os
candidatos mais desejados são os autossuficientes, o que significa que sabem aprender
coisas novas e encontrar respostas para os problemas por conta própria. Isso não significa
que eles nunca peçam ajuda; pelo contrário, um bom programador sabe quando parar de
bater a cabeça contra a parede e consultar os colegas em busca de conselhos. No entanto,
a maioria dos problemas cotidianos pode ser resolvida usando a documentação de ajuda,
exemplos de códigos online, fóruns on-line, códigos existentes que funcionam, livros de
programação e ferramentas de depuração no software.
Suponha que você esteja em uma entrevista de emprego e seu possível empregador
pergunte: "O que você faz quando encontra uma 'parede de tijolos' ao programar? Para quais
fontes você primeiro procura ajuda?" Se você responder "Meu supervisor" ou "Meus colegas
de trabalho", isso é uma bandeira vermelha, significando que você pode representar um
potencial custo de tempo para a equipe de desenvolvimento. Embora os problemas mais
difíceis exijam colaboração em grupo, uma equipe de desenvolvimento de software
competitiva não pode se dar ao luxo de "segurar a mão" de um funcionário em todas as
questões que encontra. Muitos dos candidatos mais convincentes respondem a essa
pergunta: "Google". Eles sabem que a maioria dos problemas de programação, embora
irritantes, são comuns e a resposta pode estar ao alcance dos seus dedos em menos de 30
segundos por meio de uma pesquisa na Internet bem formulada.
Nesta seção, você aprenderá sobre lugares em que pode encontrar ajuda ao trabalhar
com o Python e ao programar em geral. Você terá uma experiência muito mais fácil neste
curso se lembrar desses recursos e usá-los para concluir suas tarefas.

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.

Usando o depurador (debug) do PythonWin


Às vezes, quando outras tentativas rápidas de depuração falham, você precisa dar uma
olhada mais profunda em seu script. A maioria dos ambientes de desenvolvimento
integrados (IDEs), como o PythonWin, inclui algumas ferramentas de depuração que
permitem percorrer o script linha por linha para tentar encontrar um erro. Essas ferramentas
permitem que você “fique de olho” no valor de todas as variáveis em seu script para verificar
como elas reagem a cada linha de código. A barra de ferramentas de depuração pode ser
uma boa maneira de detectar erros lógicos em que uma linha de código incorreta está
impedindo que o seu script retorne o resultado correto. A barra de ferramentas de depuração
também pode ajudá-lo a descobrir qual linha de código está causando uma falha.
A melhor maneira de explicar os aspectos da depuração é trabalhar com um exemplo.
Desta vez, vamos olhar para algum código que tenta calcular o fatorial de um inteiro (o inteiro
é codificado para 5 neste caso). Na matemática, um fatorial é o produto de um inteiro e de
todos os inteiros positivos abaixo dele. Assim, 5! (ou "5 fatorial") deve ser 5 * 4 * 3 * 2 * 1 =
120.
O código abaixo tenta calcular um fatorial através de um loop que incrementa o
multiplicador em 1 até atingir o inteiro original. Esta é uma abordagem válida, pois 1 * 2 * 3
* 4 * 5 também renderia 120.
# Este script calcula o fatorial de um número
# inteiro, que é o produto desse inteiro e de
# todos os inteiros positivos menores que ele
numero = 5
multiplicador = 1
while multiplicador < numero:
numero *= multiplicador
multiplicador += 1

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.

• Pressione o botão Go . Isso executa seu script até o ponto de interrupção.


Agora você tem uma pequena seta amarela indicando qual linha do script você está
prestes a executar.

• Clique no botão Watch . O que é comumente conhecido como janela de


observação é exibido. Isso ajudará você a acompanhar o que acontece com suas
variáveis à medida que você executa o código linha por linha. Antes de executar qualquer
outro código, no entanto, você precisa informar à janela de observação quais variáveis
rastrear.
• Na coluna Expression da janela de observação, clique duas vezes em <New
Item> e digite o nome da sua primeira variável "numero" (omita as aspas). Na coluna
Value, você verá "NameError: name 'numero' is not defined." Isso faz sentido porque
você ainda não executou a linha de código que cria essa variável.
• Semelhante à etapa anterior, clique novamente em <New Item> e configure
para a variável "multiplicador". Você deve obter o mesmo erro sobre a variável ainda não
estar definida.

• 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.

Imprimindo mensagens da estrutura de geoprocessamento


da ESRI
Quando você trabalha com ferramentas de geoprocessamento em Python, às vezes o
script poderá falhar porque algo deu errado com a ferramenta. Pode ser que você tenha
escrito uma sintaxe Python perfeita, mas seu script não funciona como esperado porque as
ferramentas de geoprocessamento da ESRI não conseguem encontrar um conjunto de
dados ou acessar um parâmetro da ferramenta. Você não será capaz de encontrar esses
erros com o depurador, mas poderá obter uma visualização deles imprimindo as mensagens
retornadas da estrutura de geoprocessamento da ESRI.
A ESRI configurou suas ferramentas de geoprocessamento para relatar com frequência
o que estão fazendo. Quando você executa uma ferramenta de geoprocessamento a partir
do ArcMap ou ArcCatalog, você vê uma caixa com essas mensagens, às vezes
acompanhada por uma barra de progresso. Você aprendeu na etapa 1 que pode usar o
arcpy.GetMessages() para acessar essas mensagens no seu script. Se você quiser apenas
ver as mensagens quando algo der errado, você pode incluí-las em um bloco de código,
como este.
try:
. . .
except:
print (arcpy.GetMessages())
Lembre-se que ao usar try / except, no caso normal, o Python executará tudo no try-
block (= tudo seguindo o "try:" que está recuado em relação a ele) e então continuará após
o except-block (= tudo seguindo o "except:" que está recuado em relação a ele). No entanto,
se algum comando no bloco try falhar, a execução do programa salta diretamente para o
início do bloco except e, nesse caso, imprime as mensagens que recebemos de
arcpy.GetMessages(). Depois que o bloco de exceções for executado, o Python continuará
com a próxima instrução após o bloco de exceções.
As mensagens de geoprocessamento têm três níveis de gravidade: Mensagem, Aviso
e Erro. Você pode passar um índice para o método arcpy.GetMessages() para filtrar apenas
as mensagens que atingem um determinado nível de gravidade. Por exemplo,

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.

Outras fontes de ajuda


Além das abordagens acima, existem muitos outros lugares onde você pode obter
ajuda. Alguns deles são descritos abaixo. Se você é iniciante em programação, saber que
esses recursos existem e como usá-los pode ajudá-lo a se sentir mais confiante. Encontre
os que você prefira e retorne a eles com frequência. Esse hábito ajudará você a se tornar
um programador autossuficiente e aprimorará seu potencial para aprender qualquer nova
linguagem de programação ou tecnologia.
Aproveitar os recursos abaixo requer tempo e esforço. Muitas pessoas não gostam de
vasculhar a documentação do computador, e isso é compreensível. No entanto, você pode
economizar tempo se procurar a resposta em vez de esperar que alguém o ajude. Melhor
ainda, você terá aprendido algo novo a partir de sua própria experiência, e as coisas que
aprender dessa maneira serão muito mais fáceis de lembrar no futuro.
Fontes de ajuda
Motores de busca (search engines)
Os mecanismos de pesquisa são úteis para respostas rápidas e problemas obscuros.
Você esqueceu a sintaxe de um loop? A solução mais rápida pode ser o Google, pesquise
"for loop python" ou "while loop python" e examine um dos muitos exemplos de código
retornados. Os mecanismos de pesquisa são extremamente úteis para diagnosticar
mensagens de erro. Pesquise a mensagem de erro entre aspas e você pode ler as
experiências de outras pessoas que tiveram o mesmo problema. Se você não conseguir
respostas suficientes, remova as aspas para ampliar a pesquisa.
Um risco que você corre de pesquisas on-line é encontrar informações irrelevantes.
Ainda mais perigoso é usar estas informações irrelevantes. Pesquise qualquer amostra de
código para se certificar de que é aplicável à versão do Python que você está usando.
Algumas sintaxes no Python 3.x são diferentes do Python 2.x que você está usando neste
curso.
Ajuda on-line da ESRI
A Esri mantém todo o sistema de ajuda on-line e você encontrará a maioria dos tópicos
de script na seção arcpy .
Outra seção, que você deve visitar repetidamente, é a Referência de Ferramentas (tool
Reference), que descreve todas as ferramentas da caixa de ferramentas e contém exemplos
de script Python para cada uma. Se você está tendo problemas para entender quais
parâmetros entram ou saem de uma ferramenta, ou se você está recebendo um erro de volta
da própria estrutura de geoprocessamento, tente a Referência de Ferramenta antes de fazer
uma busca aleatória na Internet.
Ajuda on-line do Python
A documentação oficial do Python está disponível online. Algumas delas são muito
detalhadas e têm o tom de serem escritas por programadores para programadores. A parte
que você provavelmente achará mais útil é a referência da Python Standard Library , que é

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.

Exercícios Práticos – etapa 2


Antes de tentar começar o Projeto 2, você pode tentar alguns exercícios práticos
simples, especialmente se os conceitos desta lição forem novos para você. Lembre-se de
escolher File> New no PythonWin para criar um novo script. Você pode nomear os scripts
como preferir. Para executar um script no PythonWin, clique no ícone "running man".

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.

Exercício 2: Converter os nomes para um formato "Sobrenome, Nome"


Construa um script a partir da lista do exercício anterior que imprima cada nome na
lista no seguinte formato:
Sobrenome, Nome
Para fazer isso, você precisará encontrar a posição do espaço como antes. Para extrair
parte de uma string, você pode especificar o caractere inicial e o caractere final entre
colchetes após o nome da string, como mostrado a seguir:
nome = "Joe Paterno"
print (nome[4:11]) # imprime Paterno
Uma coisa peculiar sobre essa sintaxe é que você precisa especificar o caractere final
como 1 além do que você realmente deseja. O "o" em "Paterno" está realmente na posição
10, mas é necessário especificar um valor de 11.
Um recurso útil da sintaxe é que você pode omitir o índice do caractere final se quiser
tudo após o caractere inicial. Assim, nome[4:] retornará a mesma string como nome[4:11]
neste exemplo. Da mesma forma, o caractere inicial pode ser omitido para obter tudo, desde
o início da string até o caractere final especificado.

Exercício 3: Converter pontuações em notas de letra


Escreva um script que aceite uma pontuação de 1-100 como um parâmetro de entrada
e, em seguida, relate o grau da letra correspondente a essa pontuação. Atribuir notas de
letra da seguinte forma:

79
A:90-100
B:80-89
C:70-79
D:60-69
F:<60

Exercício 4: Criar cópias de um shapefile com base em um modelo


Imagine que você esteja novamente trabalhando com os dados de precipitação da
etapa 1 e que você queira criar cópias do arquivo shape PluTotalAnual pelos próximos 4
anos após 2018 (por exemplo, PluTotalAnual_2019, PluTotalAnual_2020, etc.).
Essencialmente, você deseja copiar o esquema de atributos do shapefile inicial, mas não os
próprios dados. Aqueles serão adicionados mais tarde. A ferramenta para automatizar esse
tipo de operação é a ferramenta para criar classe de feições na caixa de ferramentas
Gerenciamento de Dados (Create Feature Class - Data Management toolbox). Procure esta
ferramenta no sistema de Ajuda e examine sua sintaxe e o script de exemplo. Observe o
parâmetro opcional, que permite especificar uma classe de feições cujo esquema de atributo
você deseja copiar.
Para concluir este exercício, você deve invocar a ferramenta
arcpy.CreateFeatureclass_management() dentro de um loop que fará com que a ferramenta
seja executada uma vez para cada ano desejado. A função range(..) pode ser usada para
produzir a lista de anos para o seu loop.

Exercício 5: Recorte todas as classes de feições em um geodatabase


Os dados para este exercício prático consistem em dois arquivos de geodatabases: O
geodatabase FC.gdb contém diversas classes de feições. O geodatabase FC_Clip.gdb está
vazio, exceto por uma classe de feições de limite de uma região para o recorte.
Sua tarefa é escrever um script que recorte todas as classes de feições do geodatabase
FC.gdb ao limite da região contida no geodatabese FC_Clip.gdb. As classes de feições
recortadas devem ser gravadas no geodatabase FC_Clip.gdb. Anexe "Clip" ao final de todos
os nomes de classes de feições cortados.
Seu script deve ser flexível o suficiente para lidar com qualquer número de classes de
feições no geodatabase de entrada. Por exemplo, se houver 15 classes de feições no
geodatabase em vez de 3, seu código final não precisará ser alterado de nenhuma maneira.
C:\SEA5923\Dados\FC\FC.gdb
C:\SEA5923\Dados\FC\Resultados\FC_Clip.gdb.gdb

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.

A ferramenta do Projeto 2 com dois parâmetros de entrada e nenhum parâmetro de saída


A execução da ferramenta faz com que os conjuntos de dados reprojetados sejam
colocados no disco na pasta de destino.
Requisitos
• É necessário reprojetar os conjuntos de dados vetoriais shapefile na pasta para
corresponder à projeção do conjunto de dados escolhido como padrão.
• Deve-se acrescentar "_projetado" ao final de cada nome de conjunto de dados
reprojetado. Por exemplo: Rodovias_projetado.shp.
• Deve-se pular quaisquer conjuntos de dados que já estejam na projeção
padrão.
• Deve relatar uma mensagem de geoprocessamento informando quais
conjuntos de dados foram reprojetados. Nesta mensagem, os nomes dos conjuntos de
dados podem ser separados por espaços. Na mensagem, não inclua conjuntos de dados
que foram ignorados porque já estavam na projeção padrão. Esta deve ser uma única

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

No final desta etapa, você deve:


• Entender o uso de diferentes tipos de workspaces (por exemplo, geodatabases) em
Python
• Ser capaz de usar cursores arcpy para ler e manipular dados de atributos de vetores
(pesquisa de registros, atualização e exclusão)
• Saber como construir strings de consulta SQL para realizar seleção por atributo com
cursores ou MakeFeatureLayer

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

Armazenamento e recuperação de dados no ArcGIS


Antes de entrar nos detalhes de como ler e modificar esses atributos, é útil revisar como
os conjuntos de dados geográficos são armazenados no ArcGIS. Você precisa saber isso
para poder abrir conjuntos de dados em seus scripts e, ocasionalmente, criar novos
conjuntos de dados.
Geodatabases
Ao longo dos anos, a ESRI desenvolveu várias maneiras de armazenar dados
espaciais. Eles incentivam você a colocar seus dados em bancos de dados geográficos, que
são estruturas organizacionais para armazenar conjuntos de dados e definir relacionamentos
entre esses conjuntos de dados. Diferentes tipos de geodatabase são oferecidos para
armazenar diferentes magnitudes de dados.
• Os geodatabases pessoais são uma forma pequena e quase obsoleta de geodatabase
que armazena dados no sistema de arquivos local. Os dados são mantidos em um banco
de dados do Microsoft Access, que limita a quantidade de dados que podem ser
armazenados no geodatabase.
• Os geodatabases de arquivo são uma maneira mais recente de armazenar dados no
sistema de arquivos local. Os dados são armazenados em um formato proprietário
desenvolvido pela ESRI. Um file geodatabase pode conter mais dados do que um
personal geodatabase: até terabytes.
• Os geodatabases ArcSDE ou "enterprise geodatabases" armazenam dados em um
servidor central em um sistema de gerenciamento de banco de dados relacional
(RDBMS), como SQL Server, Oracle ou PostgreSQL. Estes são grandes bancos de
dados projetados para servir dados não apenas para um computador, mas para toda
uma empresa. Como trabalhar com um RDBMS pode ser um trabalho em si, a ESRI
desenvolveu o ArcSDE como um "middleware" que permite configurar e ler seus
conjuntos de dados no ArcCatalog ou no ArcMap sem fazer uso software RDBMS.
Para ações onde o ArcSDE é necessário, mas onde seria muito oneroso comprar e
configurar um RDBMS corporativo, a ESRI desenvolveu uma versão menor de
"workgroup" do ArcSDE que funciona com o banco de dados livre SQL Server Express.
E que pode ser diretamente configurado no Arc Caalog ou na janela no ArcMap.
Nos últimos anos, a ESRI também desenvolveu um novo recurso chamado “camadas de
consulta” (query layers) , que permite extrair dados diretamente de um RDBMS usando
consultas SQL, sem envolver o ArcSDE.

Um único conjunto de dados vetoriais dentro de um geodatabase é chamado de classe


de feições (Feature classes). As classes de feições podem ser organizadas opcionalmente

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.

Um file geodatabese conforme visualizado pelo sistema de arquivos do Windows Explorer


A maneira mais segura de obter os caminhos que você precisa é navegar até o conjunto
de dados no ArcCatalog e pegar o caminho que aparece na barra de ferramentas
Localização. Aqui está o mesmo arquivo geodatabase seria semelhante no ArcCatalog. O

87
caminho destacado mostra como você se referiria a uma classe de feições dentro do
geodatabase.

O mesmo arquivo geodatabase, mostrado no ArcCatalog


Abaixo está um exemplo de como você pode acessar a classe de feições em um script
Python usando esse caminho. Isso é semelhante a um dos exemplos da etapa.
import arcpy
featureClass = "C:\\SEA5923\\Dados\\BaseDados.gdb\\Limite"
desc = arcpy.Describe(featureClass)
spatialRef = desc.SpatialReference
print (spatialRef.Name)
Lembre-se de que a barra invertida (\) é um caractere reservado em Python, portanto,
será necessário usar a barra invertida dupla (\\) ou barra (/) no caminho. Outra técnica que
você pode usar para caminhos é a string raw, que permite colocar barras invertidas e outros
caracteres reservados em sua string, desde que você coloque "r" antes de suas aspas.
featureClass = r "C:\SEA5923\Dados\BaseDados.gdb\Limite"
Workspaces (local de trabalho)
A estrutura de geoprocessamento da ESRI geralmente usa a noção de um local de
trabalho para indicar a pasta ou o geodatabase onde você está trabalhando atualmente.
Quando você especifica um local de trabalho em seu script, não é necessário listar o caminho
completo para cada conjunto de dados. Quando você executa uma ferramenta, o
geoprocessador vê o nome da classe de feição e assume que ele reside no local de trabalho
que você especificou.
Os locais de trabalho são especialmente úteis para processamento em lote, quando
você executa a mesma ação em muitos conjuntos de dados no local de trabalho. Por
exemplo, você pode querer recortar todas as classes de feições em uma pasta para o limite
da região de interesse. O fluxo de trabalho para isso é:
• Definir um local de trabalho.
• Crie uma lista de classes de feições para o local de trabalho.
• Definir uma feição de recorte.
• Configurar um loop para ser executado em cada classe de feições na lista.
• Dentro do loop, executar a ferramenta Clip.

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.

Lendo dados de atributos de vetores


Agora que você sabe como abrir um conjunto de dados, vamos um pouco além e
começaremos a examinar alguns registros de dados individuais. Esta seção da lição discute
como ler e pesquisar tabelas de atributos. Essas tabelas geralmente fornecem os atributos
para feições vetoriais, mas também podem ser independentes em alguns casos. A próxima
sessão abordará como gravar dados nestas tabelas. No final da lição, vamos trabalhar com
os dados rasters.
À medida que trabalhamos com os dados, será útil acompanhar, copiando e colando o
código de exemplo nos scripts de prática. Ao longo da aula, você encontrará exercícios que
você pode praticar o que acabou de aprender. Você não é obrigado a entregar esses
exercícios, mas se você os completar, você terá uma maior familiaridade com o código que
será útil quando você começar a trabalhar no projeto desta etapa. É impossível ler um livro
ou uma lição e logo depois já escrever um código perfeito. Muito do que você aprende vem
através de tentativa e erro e do aprendizado que você faz disso. Portanto, é aconselhável
escrever códigos com frequência.

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.

Leitura através dos registros


Agora que você sabe pesquisar a tabela horizontalmente, lendo os campos que estão
disponíveis, vamos examinar como ler, verticalmente, para cima e para baixo nos registros
da tabela.
O cursor de pesquisa (search cursor)
O módulo arcpy contém alguns objetos chamados cursores que permitem que você
percorra os registros em uma tabela. Cursores não são exclusivos em script para o ArcGIS;
de fato, se você trabalhou com ArcObjects antes, este conceito de cursor provavelmente é
familiar para você.
Algumas alterações foram implementadas em como os cursores podem ser usados nas
diferentes versões do ArcGIS. Como versões mais antigas ainda estão sendo amplamente
usadas, primeiro ilustramos o uso de cursores de uma maneira que funciona tanto para
versões antigas como novas do ArcGIS. Em seguida, descrevemos as alterações
introduzidas nas versões 10.0 e superiores, que tornam o uso de cursores mais fácil, mais
robusto e exigem menos código. Nos exemplos restantes do curso, sempre começaremos
com uma versão para 10. ou superior.
O primeiro código que analisaremos é com o cursor de pesquisa, já que foi projetado
para uma leitura simples de dados. Vamos começar com o uso tradicional do cursor de
pesquisa usado principalmente em versões anteriores do ArcGIS (e ainda trabalhando hoje
para pessoas que estão reutilizando código antigo). Embora você venha a aprender que
esse código é mais detalhado do que o que você usa nas versões mais recentes do ArcGIS,
ele fornece uma compreensão mais fundamental do que o cursor de pesquisa está fazendo.
O fluxo de trabalho comum é:
• Crie o cursor de pesquisa. Isso é feito através do método arcpy.SearchCursor(). Esse
método usa vários parâmetros nos quais você especifica qual conjunto de dados e, como
opção, quais linhas específicas deseja ler.

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.

# Encontra a precipitação média em um conjunto de postos pluviométricos


import arcpy
postosPlu = "C:\\SEA5923\\Dados\\Plu_Total_Anual.shp"
# Esta linha abaixo é nova
campoPrecipitacao = "Total_2018"
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:
# Esta linha abaixo é nova
precipitacaoTotal += linha.getValue(campoPrecipitacao)
contador += 1
linha = linhas.next()
media = precipitacaoTotal / contador
print ("Média da precipitação " + str(media))
Para atualizar o script acima, você teria que definir campoPrecipitacao = "Total_2019"
próximo ao topo do script. Isso é certamente mais fácil do que pesquisar no corpo do script
para linha.Total_2018 ; no entanto, você pode ir além e permitir que o usuário insira qualquer
nome de campo que ele queira como argumento ao executar o script.
Lembre-se na etapa 1 como você aprendeu que o arcpy.GetParameterAsText() permite
que o usuário do script forneça um valor para a variável. Usar essa técnica para o caminho
da classe de feição e o nome do campo de precipitação torna o script muito flexível. Observe
que o código abaixo não contém nomes de caminhos codificados, nomes de campos ou
números além de 0 e 1. Isso significa que você pode executar o script com qualquer classe
de feições contendo qualquer nome para seu campo de precipitação sem modificar o código.
Na verdade, você pode usar código semelhante a esse para encontrar a média de qualquer
campo numérico.
# Encontra a precipitação média em um conjunto de postos pluviométricos
import arcpy
postosPlu = arcpy.GetParameterAsText(0)
# Esta linha abaixo é nova
campoPrecipitacao = arcpy.GetParameterAsText(1)
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:
# Esta linha abaixo é nova
precipitacaoTotal += linha.getValue(campoPrecipitacao)
contador += 1
linha = linhas.next()

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.

Executando o script acima no PythonWin


Usando um loop for com um cursor (introduzido no ArcGIS 10.0)
Embora os exemplos acima usem um loop while em conjunto com o método next() para
avançar o cursor, geralmente é mais fácil iterar em cada registro usando um loop for. Isso
se tornou possível a partir do ArcGIS 10.0. Veja como o exemplo acima pode ser modificado
para usar um loop for.
# Encontra a precipitação média em um conjunto de postos pluviométricos
import arcpy
postosPlu = arcpy.GetParameterAsText(0)
campoPrecipitacao = arcpy.GetParameterAsText(1)
linhas = arcpy.SearchCursor(postosPlu)
media = 0
precipitacaoTotal = 0
contador = 0
# Loop pelos registros e cálculo do total precipitado e contador
for linha in linhas:
precipitacaoTotal += linha.getValue(campoPrecipitacao)
contador += 1
media = precipitacaoTotal / contador
print ("Média da precipitação " + str(media))
Neste exemplo, o método next() nem sequer é necessário porque está implícito no loop
for que o script irá iterar em cada registro. O objeto chamado linha é declarado quando o
loop for é declarado.
Embora essa sintaxe seja mais compacta do que usar um loop while, há algum
benefício em ver como o método next() funciona, especialmente se você já trabalhou com
scripts Python do ArcGIS 9.3.x ou se usa cursores em ArcObjects (que tem conceito
semelhante para avançar um cursor linha por linha). No entanto, quando você se acostumar
a usar um loop for para percorrer uma tabela, é improvável que você deseje voltar a usar
loops while.
O módulo de acesso de dados arcpy (introduzido no ArcGIS 10.1)

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.

Recuperando registros usando uma consulta de atributo


Os exemplos anteriores usavam o objeto SearchCursor para ler cada registro em um
conjunto de dados. Você pode ser mais específico com o cursor de pesquisa instruindo-o a
recuperar apenas um subconjunto de registros cujos atributos atendem a alguns critérios,
por exemplo, "somente registros com uma precipitação maior que 1000" ou "todos os
registros que começam com as letras P - Z "
Revisando, é assim que você constrói um cursor de pesquisa para operar em cada
registro de um conjunto de dados usando o módulo arcpy.da:
with arcpy.da.SearchCursor (fc, (campo,)) as cursor:
Se você quiser que o cursor de pesquisa recupere apenas um subconjunto dos
registros com base em alguns critérios, é possível fornecer uma expressão SQL como o
terceiro argumento no construtor (o construtor é o método que cria o SearchCursor). Por
exemplo:
with arcpy.da.SearchCursor (fc, (campo,), 'Campo1 "> 1000') as cursor:
O exemplo acima usa a expressão SQL "Campo1"> 1000 para recuperar somente os
registros cuja Campo1 é maior que 1000. SQL significa "Structured Query Language" e é
uma sintaxe especial usada para consultar conjuntos de dados. Se você já usou uma
consulta para filtrar dados no ArcMap, então você teve alguma exposição a esses tipos de
consultas SQL. Se o SQL é novo para você, por favor, dedique alguns minutos para ler
Construindo uma expressão de consulta na Ajuda do ArcGIS Desktop. Este tópico é uma
introdução simples ao SQL no contexto do ArcGIS.
http://desktop.arcgis.com/en/arcmap/latest/map/working-with-layers/building-a-query-
expression.htm
Expressões SQL podem conter uma combinação de critérios que permitem identificar
um subconjunto de registros muito específicos. A complexidade da sua consulta é limitada
apenas pelos seus dados disponíveis. Por exemplo, você poderia usar uma expressão SQL
para localizar apenas cidades com uma densidade populacional superior a 100 pessoas por
km quadrado, que começam com a letra M e foram criadas após 1950.
Observe que a expressão SQL que você fornece para um cursor de pesquisa é para
consultas de atributo, não para consultas espaciais. Você não pode usar uma expressão
SQL para selecionar registros que caiam "a oeste do rio Tietê" ou "dentro do limite do estado
de SP", a menos que você tenha adicionado e preenchido algum atributo afirmando se essa
condição era verdadeira. Mais adiante nesta lição, falaremos sobre como fazer consultas
espaciais usando a ferramenta de geoprocessamento Select By Location.

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

Recuperando registros usando uma consulta espacial


A aplicação de uma expressão SQL ao cursor de pesquisa é útil apenas para consultas
de atributos, não para consultas espaciais. Por exemplo, você pode facilmente abrir um
cursor de pesquisa para todos os setores censitários de um determinado município pelo
atributo de código do município usando uma expressão SQL, mas encontrar todos os
municípios que tocam ou incluem o rio Tietê, por exemplo, requer uma abordagem diferente.
Para obter um subconjunto de registros com base em um critério espacial, é necessário usar
uma ferramenta de geoprocessamento chamada de “Select Layer By Location”.
Nota:
Alguns bancos de dados relacionais, como o SQL Server 2008, podem incluir tipos de
dados espaciais que podem ser consultados espacialmente com o SQL. O suporte para
esses tipos espaciais no ArcGIS ainda está amadurecendo e, neste curso, vamos supor que
a maneira de fazer uma consulta espacial é através da ferramenta apresentada. Como não
estamos usando o ArcSDE, isso é realmente verdade.
Aqui você precisa entender um pouco sobre como o ArcGIS trabalha com layers e
seleções. Suponha que você queira selecionar todos os estados cujos limites tocam em São
Paulo. Na maioria dos casos, você não precisará criar uma classe de feições totalmente
nova para manter esses estados específicos; você provavelmente só precisará manter esses
registros de estado específicos na memória do computador por um curto período de tempo
enquanto atualiza algum atributo. O ArcGIS usa o conceito de camadas de feições (feature
layers) para representar conjuntos de registros em memória de uma classe de feições.
A ferramenta Make Feature Layer cria uma camada de feição a partir de alguns ou de
todos os registros em uma classe de feição. Você pode aplicar uma expressão SQL ao
executar a opção Make Feature Layer para restringir os registros incluídos na camada de
feição com base nos atributos. Posteriormente, você pode usar Select Layer By Location
para restringir os registros na camada de feição com base em alguns critérios espaciais.
Abrir um cursor de pesquisa estado de São Paulo e em todos os estados que fazem
fronteira com ele levaria quatro etapas:
• Use a ferramenta Make Feature Layer para criar uma camada de feição de todos os
estados. Vamos chamar isso de camada “todosEstados”.
• Use a opção Make Feature Layer para criar uma segunda camada de feições apenas de
São Paulo. (Para obter São Paulo sozinho, você aplicaria uma expressão SQL ao criar a
camada de feição.) Vamos chamar isso de “layerSelEstados”.
• Use a ferramenta Select Layer By Location para restringir a camada todosEstados (a
camada criada anteriormente) para apenas os estados que tocam em layerSelEstados.

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.

Abaixo está um código que aplica as etapas acima.


# Seleciona todos estados que fazem fronteira com um estado selecionado
import arcpy
# Recupera o layer de estados, e o nome do campo para o nome dos estados
estadosLayer = "C:\SEA5923\Dados\Estados\Estados.shp"
estado = "São Paulo"
nomeCampo = "Nome"
try:
# Make a feature layer com todos os estados
arcpy.MakeFeatureLayer_management(estadosLayer, "todosEstados")

# Make a feature layer contend somente São Paulo


arcpy.MakeFeatureLayer_management(estadosLayer, "layerSelEstados",
'"' + str(nomeCampo) + '" =' + "'" + str(estado) + "'")

# Aplica a seleção para o layer dos estados

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

Escrevendo atributos em dados de vetores


Da mesma forma que você usa cursores para ler dados de atributos de vetores, você
também usa cursores para gravar dados. Dois tipos de cursores são fornecidos para gravar
dados:
• Update cursor - este cursor edita valores em registros existentes ou exclui registros
• Insert cursor - este cursor insere novos registros
Nas seções a seguir, você aprenderá sobre esses dois cursores e obterá algumas dicas
para usá-los.
Leitura obrigatória
A Ajuda do ArcGIS Desktop tem alguma explicação sobre os cursores. Familiarize-se
com essa ajuda, pois ela o preparará para as próximas seções da lição. Você também achará
útil retornar aos exemplos de código enquanto trabalha no Projeto 3:
Acessando dados usando cursores
http://desktop.arcgis.com/en/arcmap/latest/analyze/python/data-access-using-
cursors.htm
Siga também os três links da tabela no início do tópico acima. Estes explicam
brevemente o InsertCursor, SearchCursor e UpdateCursor e fornecem um exemplo de
código para cada um. Você já trabalhou com o SearchCursor, mas examine atentamente os
exemplos de código para os três tipos de cursor e veja se consegue determinar o que está
acontecendo em cada um deles.
http://desktop.arcgis.com/en/arcmap/latest/analyze/arcpy-data-access/insertcursor-
class.htm
http://desktop.arcgis.com/en/arcmap/latest/analyze/arcpy-data-access/searchcursor-
class.htm
http://desktop.arcgis.com/en/arcmap/latest/analyze/arcpy-data-access/updatecursor-
class.htm

Atualizando registros existentes


Use o cursor de atualização para modificar os registros existentes em um conjunto de
dados. Aqui estão os passos gerais para usar o cursor de atualização:
• Crie o cursor de atualização chamando arcpy.da.UpdateCursor(). Você pode,
opcionalmente, passar uma expressão SQL como um argumento para esse método.
Essa é uma boa maneira de restringir as linhas que você deseja editar se você não estiver
interessado em modificar todas as linhas da tabela.
• Use um loop for para percorrer as linhas e para cada linha ...

102
• Modifique os valores do campo na linha que precisam de atualização (veja abaixo).
• Chame UpdateCursor.updateRow() para finalizar a edição.

Modificando valores de campo


Quando você cria um UpdateCursor e percorre as linhas usando uma variável chamada
“linha”, é possível modificar os valores do campo fazendo atribuições usando a sintaxe
linha[<index do campo que deseja alterar>] = <o novo valor> . Por exemplo:
linha[0] = "Fulano de Tal"
É importante observar que o índice que ocorre para determinar [...] qual campo será
alterado é dado com relação à tupla de campos fornecidos quando o UpdateCursor é criado.
Por exemplo, se criarmos o cursor usando o seguinte comando
with arcpy.da.UpdateCursor (fc, ("empresa", "proprietario")) as cursor:
linha [0] refere-se ao campo denominado "empresa" e a linha [1] refere-se ao campo
que possui o nome "proprietario".
Exemplo
O script abaixo executa uma operação de "pesquisa e substituição" em uma tabela de
atributos. Por exemplo, suponha que você tenha um conjunto de dados representando
postos pluviométricos. Existe um campo da tabela de atributos que indica o órgão
responsável pela manutenção do posto. Imagine que um destes órgãos foi substituido. Você
precisa encontrar todas as instâncias respectivas ao órgão substituído e alterá-las pelo novo
nome do órgão substituto. Esse script pode executar essa tarefa automaticamente.

# Exemplo de script de pesquisa e substituição


import arcpy
# Parâmetros de entrada: a classe de feição, o campo afetado
# pela pesquisa e substituição, o termo de pesquisa e o termo de
# substituição.
fc = arcpy.GetParameterAsText(0)
campoAfetado = arcpy.GetParameterAsText(1)
valorAntigo = arcpy.GetParameterAsText(2)
valorNovo = arcpy.GetParameterAsText(3)
# Criando a expressão SQL para o update cursor
expressaoSQL = '"' + campoAfetado + '" = ' + "'" + valorAntigo + "'"
# Cria update cursor e atualiza cada linha retornada pela expressão SQL
with arcpy.da.UpdateCursor(fc, (campoAfetado,), expressaoSQL) as cursor:
for linha in cursor:
linha[0] = valorNovo
cursor.updateRow(linha)
del linha, cursor
Observe que esse script é relativamente flexível porque recebe todos os parâmetros
como texto. No entanto, esse script pode ser executado apenas em variáveis de string devido
à maneira como a string de consulta é configurada. Observe que o valor antigo é colocado
entre aspas, assim: "'" + valorAntigo + "'". O manuseio de outros tipos de variáveis, como
inteiros, teria tornado o exemplo mais longo.
Novamente, é essencial entender a tupla dos campos afetados que você passa quando
cria o cursor de atualização. Neste exemplo, há apenas um campo afetado (que chamamos

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

Inserindo novos registros


Ao adicionar um novo registro a uma tabela, você deve usar o cursor de inserção. Aqui
está o fluxo de trabalho para cursores de inserção:
• Crie o cursor de inserção usando arcpy.da.InsertCursor() .
• Chame InsertCursor.insertRow() para adicionar uma nova linha ao conjunto de dados.
Como com o cursor de pesquisa e atualização, você pode usar um cursor de inserção
junto com a instrução "with" para evitar problemas de bloqueio.
Os cursores de inserção diferem dos cursores de pesquisa e atualização, pois você
não pode fornecer uma expressão SQL ao criar o cursor de inserção. Isso faz sentido porque
um cursor de inserção está preocupado apenas em adicionar registros à tabela. Não precisa
"saber" sobre os registros existentes ou qualquer subconjunto deles.
Quando você insere uma linha usando InsertCursor.insertRow (), você fornece uma
tupla de valores separados por vírgulas para os campos da nova linha. A ordem desses
valores deve corresponder à ordem de valores da tupla de campos afetados que você
forneceu quando criou o cursor. Por exemplo, se você criar o cursor usando

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.

Trabalhando com rasters


Até agora, nesta lição, seus scripts apenas leram e editaram conjuntos de dados
vetoriais. Este trabalho consiste, em grande parte, em percorrer tabelas de registros e ler e
escrever valores em determinados campos. Os dados rasterizados são muito diferentes e
consistem apenas em uma série de células, cada uma com seu próprio valor. Então, como
você acessa e manipula dados raster usando o Python?
É improvável que você precise percorrer célula por célula usando o Python, e essa
técnica está fora do escopo deste curso. Em vez disso, você geralmente usa ferramentas
predefinidas para ler e manipular rasters. Essas ferramentas foram projetadas para operar
em vários tipos de rasters e executar os cálculos célula por célula para que você não precise.
No ArcGIS, a maioria das ferramentas que você usará ao trabalhar com rasters estará
no conjunto de ferramentas Data Management> Raster ou na caixa de ferramentas do
Spatial Analyst. Essas ferramentas podem reprojetar, recortar, mosaicar e reclassificar
rasters.
A caixa de ferramentas do Spatial Analyst também contém ferramentas para executar
álgebra de mapas em rasters. Multiplicar ou adicionar muitos rasters juntos usando a álgebra
de mapas é importante para cenários de seleção de locais em SIG. Por exemplo, você pode
estar tentando encontrar a melhor localização para um novo aterro sanitário e tem sete
critérios que devem ser atendidos. Se você pode criar uma varredura booleana (contendo 1
para adequado, 0 para inadequado) para cada critério, você pode usar a álgebra de mapa
para multiplicar os rasters e determinar quais células recebem uma pontuação de 1,
atendendo a todos os critérios. (Alternativamente, você pode adicionar os rasters e
determinar quais áreas receberam um valor de 7).
A parte complicada da álgebra do mapa é a construção da expressão, que é uma string
que indica o que a operação de álgebra do mapa deve fazer. O ArcGIS Desktop contém
interfaces para construir uma expressão para execuções únicas da ferramenta. Mas e se
você quiser executar a análise várias vezes ou com diferentes conjuntos de dados? É um

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

Rasters e extensões de arquivo


O script de exemplo acima usa a extensão de arquivo para os rasters .tif. Ocorre que
os rasters que não usam extensões são atribuidos o formato ESRI GRID. Se você tiver
rasters em outro formato, como .jpg, será necessário adicionar a extensão de arquivo
correta. Se você não tiver certeza da sintaxe a ser usada ao fornecer um nome de arquivo
raster, destaque o raster no ArcCatalog e observe como o caminho aparece na barra
Location.
Se você observar rasters como o ESRI GRID no Windows Explorer, poderá ver que
eles consistem em vários arquivos de suporte com diferentes extensões, às vezes até
contidos em uma série de pastas. Não tente adivinhar um dos arquivos para referência; em
vez disso, use o ArcCatalog para obter o caminho para o raster. Quando você usa esse
caminho, os arquivos e pastas de suporte funcionarão juntos automaticamente.
Leituras
O capítulo 9 de Zandbergen cobre muitas funções adicionais que você pode executar
com rasters e tem alguns bons exemplos de código.

Exercícios Práticos – etapa 3

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.

Projeto 3: Manipulando dados vetoriais

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

Entregas para este projeto são as seguintes:


• O arquivo .py de origem contendo seu script
• Um curto artigo (cerca de 300 palavras) descrevendo como você abordou o projeto, como
você lidou com os obstáculos e com o que aprendeu ao longo do caminho. Você deve
incluir os requisitos que você não cumpriu. Se você adicionou algum plus à ferramenta,
indique-os para que possamos analisá-los.

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.

É importante entender os mecanismos de (a) saltar da chamada da função (linha 5)


para o código da definição da função e voltar, e de (b) criar variáveis locais para o(s)
parâmetro(s) e todas as novas variáveis definidos no corpo da função e como são
descartados novamente quando o fim do corpo da função é atingido. O valor de retorno é a
única informação que permanece e é devolvida da execução da função.
Uma função (cálculo) não é estritamente necessária para retornar algum valor. Por
exemplo, você pode ter uma função que usa o caminho de um arquivo de texto como um
parâmetro, lê a primeira linha do arquivo e imprime essa linha na Janela Interativa. Como
toda a lógica de impressão é executada dentro da função, não há realmente nenhum valor
de retorno.
Da mesma forma, não é de todo necessário que a função receba algum parâmetro. Por
exemplo, você pode escrever uma função que recupere ou calcule algum valor estático.
Tente isso na janela interativa:
>>> def presidenteAtual():
... return "Jair Bolsonaro"
...
>>> presidente = presidenteAtual()
>>> print (presidente)
Jair Bolsonaro
A função presidenteAtual() não aceita nenhum parâmetro fornecido pelo usuário. Seu
único "propósito na vida" é devolver o nome do atual presidente.
Módulos
Você pode estar se perguntando qual vantagem você ganha colocando a lógica
presidenteAtual() acima em uma função. Por que você não pode simplesmente definir uma
string presidenteAtual e defini-la como "Jair Bolsonaro"? O grande motivo é a reutilização.
Suponha que você mantenha 20 scripts diferentes, cada um dos quais trabalha com o
nome do atual presidente de alguma forma. Você sabe que o nome do atual presidente
acabará mudando. Portanto, você poderia colocar essa função no que é conhecido como
um arquivo de módulo e fazer referência a esse arquivo dentro de seus 20 scripts diferentes.
Quando o nome do presidente muda, você não precisa abrir 20 scripts e alterá-los. Em vez
disso, basta abrir o arquivo do módulo e fazer a alteração uma vez.
Você pode lembrar que já trabalhou com alguns dos módulos internos do Python.O
exemplo Hi Ho! Cherry O da etapa 2 importou o módulo randon para que o script pudesse
gerar um número aleatório para o resultado da roleta. Isso poupou o esforço de escrever ou
colar qualquer código que gera números aleatórios em seu script.
Você provavelmente já se acostumou com o padrão de importação do módulo arcpy
no início de seus scripts. Na verdade, o módulo arcpy é o que chamamos de site package.
Um site package pode conter vários módulos. No caso do arcpy, esses módulos incluem
funções ESRI para geoprocessamento.
Como você usa o Python no seu trabalho SIG, você provavelmente irá escrever funções
que são úteis em muitos tipos de scripts. Essas funções podem converter uma coordenada

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.

Lendo e analisando texto usando o módulo csv do Python


Uma das maneiras de ampliar suas opções como programador SIG é aprender como
manipular informações baseadas em texto. Na etapa 3, falamos sobre como ler dados em
formatos nativos do ArcGIS, como classes de feições. Mas, com frequência, os dados
espaciais para SIG são coletados e compartilhados em formatos mais "brutos", como uma
planilha no formato CSV (valores separados por vírgula), uma lista de coordenadas em um
arquivo de texto ou uma resposta XML recebida por um serviço da Web.
Quando confrontado com esses arquivos, você deve primeiro verificar se o seu
software SIG já possua uma ferramenta ou script que pode ler ou converter os dados para
um formato que possa usar. Se nenhuma ferramenta ou script existir, você precisará fazer
algum trabalho programático para ler o arquivo e separar as partes do texto que realmente
precisa. Isso é chamamos de análise do texto.
Por exemplo, um serviço da Web pode retornar muitas linhas de XML descrevendo
todas as leituras em uma estação meteorológica, quando tudo o que você está realmente
interessado são as coordenadas da estação meteorológica e a temperatura média anual.
Analisar a esses dados envolve escrever algum código para ler as linhas e tags no XML e
isolar apenas esses três valores.

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 = []

# Loop através das linhas no arquivo para obter cada coordenada


for linha in leitorCSV:

124
lat = linha[indiceLat]
lon = linha[indiceLong]
listaCoord.append ([lat, lon])

# Imprimir a lista de coordenadas


print (listaCoord)
Observe algumas coisas importantes sobre o código acima:
• listaCoord na verdade contém várias listas pequenas dentro de uma lista grande. Cada
lista pequena é um par de coordenadas que representa a localização de x (longitude) e
y (latitude) de uma leitura de GPS.
• O método list.append() é usado para adicionar itens a listaCoord. Observe novamente
que você pode anexar uma lista em si (representando o par de coordenadas) usando
este método.

Código completo para o exemplo


Aqui está o código completo para o exemplo.
# Este script lê um arquivo GPS track em formato CSV e
# imprime os pares de coordenadas
import csv
# Definindo as variáveis de entrada e saída
gpsTrack = open("C:\\SEA5923\\Dados\\gps_track.txt", "r")
# Definindo o objeto leitor CSV processando o cabeçalho
leitorCSV = csv.reader(gpsTrack)
cabecalho = leitorCSV.next()
indiceLat = cabecalho.index("lat")
indiceLong = cabecalho.index("long")
# Criando uma lista vazia
listaCoord = []
# Percorrendo as linhas do arquivo e armazenando as coordenadas
for linha in leitorCSV:
lat = linha[indiceLat]
lon = linha[indiceLong]
listaCoord.append([lat,lon])
# Imprimindo a lista de coordenadas
print (listaCoord)
Aplicações deste roteiro
Você pode estar perguntando neste ponto: "O que essa lista de coordenadas faz para
mim?" Evidentemente, os dados ainda são muito "crus". Não pode ser lido diretamente neste
estado por um SIG. No entanto, ter as coordenadas em uma lista do Python facilita o acesso
a outros formatos que podem ser visualizados. Por exemplo, essas coordenadas podem ser
escritas em pontos em uma classe de feições ou vértices em uma classe de feições de
polilinha ou polígono. A lista de pontos também pode ser enviada para um serviço da Web
para geocodificação reversa ou para localizar o endereço associado a cada ponto. Os pontos
também podem ser plotados em um mapa da Web usando ferramentas de programação
como a API do Google Maps. Ou, se você estivesse se sentindo realmente ambicioso,
poderia usar o Python para escrever um novo arquivo no formato KML, que poderia ser
visualizado no Google Earth.

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.

Criando feições (geometrias)


Ao analisar informações geográficas de dados "brutos", como arquivos de texto,
convém convertê-las em um formato que seja nativo do seu SIG. Esta seção da lição discute
como gravar geometrias vetoriais em classes de feições do ArcGIS. Vamos ler o mesmo
arquivo de texto GPS da seção anterior, mas desta vez adicionaremos a etapa extra de
escrever cada coordenada em uma classe de feições na forma de polilinhas.
Você já teve alguma experiência ao criar geometrias de pontos quando aprendemos
sobre cursores de inserção. Nós usamos arcpy.Point() para criar um objeto Point e então
usamos este objeto como parâmetro para tupla de insertRow() referida para o campo de
geometria identificado como "SHAPE@".
# Criar ponto
ponto = arcpy.Point (-121,34, 47,1)
...

# Criar nova linha


cursor.insertRow((ponto,))
Para polilinhas e polígonos, você cria vários objetos Point que você adiciona a um
objeto Array. Então você faz cria um objeto Polyline ou Polygon usando o array. Com
polígonos, é uma boa prática tornar o vértice final o mesmo que o vértice inicial, se possível.
O código abaixo cria uma matriz vazia (array) e adiciona três pontos usando o método
Array.add(). Em seguida, a matriz é usada para criar um objeto Polyline.
O primeiro parâmetro que você passa ao criar uma polilinha é o array que contém os
pontos da polilinha. O segundo parâmetro é uma referência espacial das coordenadas, que
você deve sempre passar para garantir que a precisão de seus dados seja mantida.

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)

# Escrevendo a matriz numa feature class como uma polilinha


with arcpy.da.InsertCursor(polilinhaFC, ("SHAPE@",)) as cursor:
polilinha = arcpy.Polyline(matrizVertices, referenciaEspacial)
cursor.insertRow((polilinha,))

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

# Definindo uma função para adicionar polilinhas


def addPolilinha(cursor, matriz, sr):
polilinha = arcpy.Polyline(matriz, sr)
cursor.insertRow((polilinha,))
matriz.removeAll()

# Corpo principal do script

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()

# Se iniciar uma nova linha, adicione a linha completa a feature class


if novo == "TRUE":
No código acima, o método upper () converte a string em maiúsculas, portanto, não
precisamos nos preocupar se a linha traz "true", "True" ou "TRUE". Mas há outra situação
que temos que lidar: e a primeira linha do arquivo? Essa linha começa com o valor "true",
mas não podemos adicionar uma polilinha existente ao arquivo, porque ainda não há uma.
Observe que uma segunda verificação é executada para garantir que haja mais de zero
pontos na matriz antes de a matriz ser gravada no shapefile:

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

# Definindo uma função para adicionar polilinhas


def addPolilinha(cursor, coordenadas, sr):
cursor.insertRow((coordenadas,))
coordenadas = [] # Limpa a lista de coordenadas

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

Executando qualquer ferramenta do Toolbox


Cedo ou tarde, você terá que incluir uma ferramenta de geoprocessamento em seu
script que você nunca tenha executado antes. É possível que você nunca tenha ouvido falar
da ferramenta muito menos ter incluído-a em um script.
Em outros casos, você pode conhecer a ferramenta muito bem, mas você pode não ter
certeza de como repassar todos os parâmetros necessários.
A abordagem para essas duas situações é a mesma. Aqui estão alguns passos
sugeridos para executar qualquer ferramenta das caixas de ferramentas do ArcGIS usando
Python:
• Encontre a documentação de referência da ferramenta. Já vimos isso durante o curso.
Cada ferramenta tem seu próprio tópico na seção de referência de ferramentas da Ajuda
do ArcGIS. Abra esse tópico e leia antes de fazer qualquer outra coisa. Leia a seção
"Uso" no começo para se certificar de que é a ferramenta certa para você e que você
está prestes a usá-la corretamente.
http://desktop.arcgis.com/en/arcmap/latest/tools/main/a-quick-tour-of-geoprocessing-
tool-references.htm

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.

Trabalhando com documentos de mapa


Até este ponto, falamos sobre a automação de ferramentas de geoprocessamento,
atualização de dados SIG e leitura de arquivos de texto. No entanto, não cobrimos nada
sobre como trabalhar com um documento de mapa da ESRI. Há muitas tarefas que podem
ser executadas em um documento de mapa que são adequadas para automação. Esses
incluem:
• Encontrar e substituir texto em um mapa ou série de mapas. Por exemplo, um aviso de
direitos autorais substituindo o ano de 2015 por 2016.
• Reparando camadas que estão referenciando fontes de dados usando os caminhos
errados. Por exemplo, seu mapa estava em um computador onde todos os dados
estavam em C:\Dados\ e agora está em um computador onde todos os dados estão em
D:\MeusDados\.

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

Limitações do script Python em ArcGIS


Neste curso, você aprendeu os conceitos básicos de programação e viu como o Python
pode automatizar qualquer função SIG que possa ser executada com as caixas de

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

Exercícios Práticos – etapa 4

Exercício 1 – Descobrindo o estado misterioso


Este exercício prático é projetado para dar a você alguma experiência para escrever
geometrias em um shapefile. Você tem na pasta C:\SEA5923\Dados\ dois arquivos para usar
neste exercício:
• Um arquivo de texto (estado_misterioso.csv) contendo as coordenadas de um limite de
um estado.
• Um shapefile de polígono vazio (Estado_Misterioso.shp) que usa um sistema de
coordenadas geográficas.

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.

Projeto 4: Rastreamento de rinocerontes


Neste projeto, você está trabalhando para um grupo de conservação da vida selvagem
que está rastreando rinocerontes na savana africana. Os recursos de software e a
experiência em SIG de seus observadores de campo são limitados, mas você conseguiu
obter uma planilha CSV mostrando as posições de alguns rinocerontes ao longo do tempo.
Cada registro na planilha mostra a coordenada de latitude / longitude de um rinoceronte junto
com o nome do rinoceronte (esses rinocerontes são bem conhecidos de seus observadores
de campo).
Sua tarefa é escrever um script que transformará as leituras da planilha em um conjunto
de dados vetoriais que você pode colocar em um mapa. Este será um conjunto de dados de
polilinha mostrando as faixas que os rinocerontes seguiram ao longo do tempo em que os
dados foram coletados.
Por favor, leia cuidadosamente todas as instruções a seguir antes de iniciar o projeto.
Você não é obrigado a usar funções neste projeto, mas você pode ganhar pontos e tempo,
quebrando código repetitivo em funções.
Entregas
Este projeto tem as seguintes entregas:
• Seu plano par aresolver para este problema de programação, escrito em pseudocódigo
em qualquer editor de texto. Isso deve consistir apenas em etapas curtas e focadas,
descrevendo o que você vai fazer para resolver o problema.
• Um script em Python que lê os dados da planilha e cria, do zero, um shapefile de polilinha
com n polilinhas, sendo n o número de rinocerontes na planilha. Cada polilinha deve
representar cronologicamente a trilha de um rinoceronte desde o início da planilha até o
final da planilha. Cada polilinha também deve ter um atributo de texto contendo o nome
do rinoceronte. O shapefile deve usar o sistema de coordenadas geográficas WGS 1984.
• Um breve resumo (~ 300 palavras) explicando o que você aprendeu durante este projeto
e quais requisitos você cumprir ou deixou de cumprir. Descreva também qualquer esforço
adicional que você conseguiu incluir ao projeto.

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):

Trajetos dos rinocerontes

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.

Exercício 2: Converter os nomes para um formato "Sobrenome, Nome"


beatles = ["John Lennon", "Paul McCartney", "Ringo Starr", "George
Harrison"]
for cantor in beatles:
espaco = cantor.index(" ")
sobrenome = cantor[espaco+1:]
nome = cantor[:espaco]
print(sobrenome + ", " + nome)
# sem utilizar as variáveis nome e sobrenome poderíamos ter
# print(cantor[espaco+1:] + ", " + cantor[:espaco])
Explicação:
Esse script usa um loop for para processar cada item na lista de beatles. E o método
de índice é novamente usado para determinar a posição dos espaços nos nomes. O script
então obtém todos os caracteres após o espaço (cantor[espaco + 1:]) e os armazena em
uma variável chamada “sobrenome”. Da mesma forma, ele obtém todos os caracteres antes
do espaço (cantor[:espaco]) e os armazena em uma variável chamada “nome”. Novamente,
a concatenação de strings é usada para acrescentar o primeiro nome ao sobrenome com
uma vírgula entre eles.

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.

Exercício 4: Criar cópias de um shapefile com base em um modelo


import arcpy
try:
arcpy.env.workspace = "C:\\SEA5923\\Dados\\"
modelo = "PluTotalAnual.shp"
for ano in range(2019,2023):
arquivoNovo = "PluTotalAnual_" + str(ano) + ".shp"
arcpy.CreateFeatureclass_management(arcpy.env.workspace,
arquivoNovo, "POINT", modelo, "DISABLED", "DISABLED", modelo)
except:
print (arcpy.GetMessages())

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).

Exercício 5: Recorte todas as classes de feições em um geodatabase


Aqui apresentamos uma forma de abordar este exercício.
Se você é iniciante em programação, recomendo que você tente descobrir uma solução
antes de estudar essa solução.
#Este script recorta todas as FC de um geodatabase
import arcpy
# Cria as variáveis para os caminhos
entrada = "C:\\SEA5923\\Dados\\FC\\FC.gdb"
destino = "C:\\SEA5923\\Dados\\FC\\Resultados\\FC_Clip.gdb"
clipFC = "C:\\SEA5923\\Dados\\FC\\Resultados\\FC_Clip.gdb\\Consorcio_mun"
# Cria uma lista para todas as FC dentro do geodatabase
arcpy.env.workspace = entrada
fcLista = arcpy.ListFeatureClasses()
try:
# percorrendo todas as FC da lista
for fc in fcLista:
# Constrói o caminho de saída
saidaFC = destino + "\\" + fc + "_Clip"
# Realiza o recorte e reporta o que está acontecendo
arcpy.Clip_analysis(fc, clipFC, saidaFC)
arcpy.AddMessage("Salvando arquivo recortado " + saidaFC + ". ")
print ("Salvando arquivo recortado " + saidaFC + ". ")
except:
# Reporta se ocorreu algum erro
arcpy.AddError("Não pode recortar as classes de feições")
print ("Não pode recortar as classes de feições ")
print (arcpy.GetMessages())

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")

# criando um update cursor e percorrendo os registros selecionados


with arcpy.da.UpdateCursor("cidadesLayer", (campoPostos,)) as cursor:
for linha in cursor:
# Atualiza o campo para verdadeiro e incrementa o contador
linha[0] = "Verdadeiro"
cursor.updateRow(linha)
cidadesComPostos +=1

# Deleta os feature layers mesmo com algum erro na execução


finally:
arcpy.Delete_management("postosFluLayer")
arcpy.Delete_management("cidadesLayer")
del linha, cursor
# Contagem total de cidades
totalCidadesContador = arcpy.GetCount_management(cidades)
totalCidadesInt = int(totalCidadesContador.getOutput(0))
# Calcula a pocentagem e print o resultado
perCidadesComPostos = ((1.0 * cidadesComPostos) / totalCidadesInt) * 100
print (str(perCidadesComPostos) + r" % de cidades contêm postos Flu.")

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.

# Este script determina a porcentagem de cidades com 5 ou mais postos


import arcpy

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

# ***** DEFININDO FUNÇÕES *****


# Esta função verifica se o nr de gols lido é maior que o maior já
# armazenado
def verificaGols(time, gols, dicionario):
# Verifica se o time tem uma chave no dicionário
if time in dicionario:
# Se uma chave é encontrada, testa para o número de gols
if gols > dicionario[time]:
dicionario[time] = gols
else:
pass
# Se não encontra a chave, adiciona uma com o nr de gols
else:
dicionario[time] = gols

# ***** Iniciando o script *****

import csv

# Abre o arquivo de texto com as partidas


caminhoArquivo = "C:\\SEA5923\\Dados\\futebol.txt"
arquivo = open(caminhoArquivo)

# Lê a linha de cabeçalho e importa os índices


leitorCSV = csv.reader(arquivo, delimiter=" ")
cabecalho = leitorCSV.next()

indiceVencedor = cabecalho.index("Vencedor")
indiceGolsVencedor = cabecalho.index("GV")
indicePerdedor = cabecalho.index("Perdedor")
indiceGolsPerdedor = cabecalho.index("GP")

# Cria um dicionário vazio. Cada chave será o nome de um time


# Cada valor será o máximo nr de gols para aquele time
maxGolsDicionario = {}

for linha in leitorCSV:

# Cria variáveis para todos os ítens de interesse da linha


vencedor = linha[indiceVencedor]
golsVencedor = linha[indiceGolsVencedor]
perdedor = linha[indicePerdedor]
golsPerdedor = linha[indiceGolsPerdedor]

# Verifica o nr de gols do vencedor contra o maior valor armazenado


verificaGols(vencedor, golsVencedor, maxGolsDicionario)

# Faz a mesma verificação para o perdedor

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

Você também pode gostar