Usando Python e o geoprocessing framework #2
Boa tarde pessoal!
Continuando naquele nosso projetinho, hoje vamos falar sobre a classe em Python que atualiza nossos dados em um determinado banco de dados. Temos algumas particularidades quando trabalhamos com ArcSDE, (registro de camadas como versionadas/não versionadas), portanto mostrarei como trabalhar com um Geodatabase local. A alteração para ArcSDE não é tão grande, e com um cadinho de pesquisa vocês conseguem fazer.
Lembre-se das outras classes que precisamos, mostradas no post anterior.
Construiremos duas classes, uma chamada GeoprocessorWrapper, um "embrulho" do objeto geoprocessor da ESRI. Isto não necessário, mas facilita, já que facilitamos algumas operações através deste "embrulho". A outra será uma tarefa, que juntará todos os dados e resultados das classes anteriores para atualizar nosso banco de dados.
Vamos começar com a mais simples, geoprocessorWrapper:
import arcgisscripting, logHandler
__toolboxAliases = [
"analysis",
"management",
"3d",
"cartography",
"arc",
"interop",
"geocoding",
"ga",
"lr",
"md",
"na",
"samples",
"sa",
"stats"]
class geoprocessorWrapperClass():
def __init__(self,workspace,toolboxList,overwriteOutput=False):
self.logs = logHandler.logHandlerClass()
# Startup logging object
self.gp = arcgisscripting.create(9.3)
# Startup ESRI geoprocessing object
self.gp.Workspace = workspace
self.gp.OverwriteOutput = overwriteOutput
# Define overwrite output. Default is to FALSE.
#lista de toolboxes disponiveis
self.toolboxList = []
self.toolboxList += toolboxList
self.buildGeoprocessorOptions(toolboxList)
def buildGeoprocessorOptions(self):
for x in self.toolboxList:
try:
if x in __toolboxAliases:
self.gp.AddToolbox(x)
except:
self.logs.newLogMessage(self, "Error in adding " + x + " toolbox to geoprocessor object. Are you sure this toolbox exists?" + self.gp.GetMessages(), "Geoprocessing Error")
# adds all toolboxes to current geoprocessing object.
def changeWorkspace(self,workspace):
self.gp.Workspace = workspace;
# changes the current workspace in geoprocessing object
def removeToolboxes(self,toolboxList):
for x in self.toolboxList:
try:
self.gp.RemoveToolbox(x)
self.toolboxList.remove(x)
self.logs.newLogMessage(self,"Removed " + x + "toolbox from geoprocessing object.","Information")
except:
self.logs.newLogMessage(self,self.gp.GetMessages(),"Geoprocessing Error")
# removes unneeded toolboxes from current geoprocessing object
Vamos começar com alguns detalhes desta classe:
Em primeiro lugar, temos os tradicionais import x. Eles são responsáveis por disponibilizar outras bibliotecas ao nosso código. Note que importamos o módulo arcgisscripting.
Logo depois, temos uma lista dos aliases que cada toolbox possui no Python. É necessário adicionar uma toolbox ao objeto geoprocessing para que se tenha acesso às ferramentas da mesma - o que pode ser feito de dois jeitos, pelo caminho da toolbox (C:Program Files...ArcGisToolbox.tbx) ou pelo seu apelido. A primeira maneira é útil para adicionar toolboxes customizadas, que não tem apelido. A segunda maneira é mais prática para adicionar as toolboxes tradicionais.
O construtor da classe toma dois parâmetros obrigatórios e um opcional para inicializar a classe. O workspace é a pasta onde iremos trabalhar - ele poderia ser também um geodatabase, mas neste caso, uma pasta. toolboxList é uma lista com os apelidos das toolboxes que queremos adicionar ao nosso objeto de geoprocessing. O parâmetro adicional é se você deseja que os resultados do objeto geoprocessing sejam escritos por cima dos anteriores (caso tenham o mesmo nome) e é por default, falso.
O construtor é bastante simples. Ele cria um objeto geoprocessing, utilizando a versão 9.3 como opção (ajuste para sua versão caso necessário - mas não garanto que funcione na 9.2 - já que vários métodos como ListDatasets, têm uma resposta diferente do que
na versão 9.3), define qual é o workspace inicial e adiciona as toolboxes relevantes.
A forma de uso é a seguinte:
g = geoprocessorWrapper.geoprocessorWrapperClass(r"C:",["analysis","management","lr"])
#ou
g = geoprocessorWrapper.geoprocessorWrapperClass(r"C:",["analysis","management","lr"],true)
# para acessar o geoprocessor do nosso wrapper, use:
listaDeFeatureClasses = g.gp.ListFeatureClasses()
for x in listaDeFeatureClasses:
print x.FeatureType
Bem simples né? Temos um método também para mudar de workspace, sem necessitar de criarmos uma nova ferramenta. O outro método disponível é para remover toolboxes que não precisamos. Um método aqui poderia ser facilmente criado para adicionar novas toolboxes ao objeto. Alguém se arrisca?
Com esta classe podemos fazer quaisquer operações, mas utilizaremos uma outra classe para realizar todo o trabalho sujo. Lembra-se do código do post passado? Temos disponível em nossa máquina um arquivo .zip extraído em uma pasta qualquer, correto?
Vamos à classe geodatabaseUpdateTask.
import os, sys
class geodatabaseOperationClass():
def __init__(self,geoprocessor,inputShapefile,outputGeodatabase,outputFeatureDataset,outputFeatureClass):
self.geoprocessorWrapperClass = geoprocessor
self.inputShapefile = inputShapefile
self.outputGeodatabase = outputGeodatabase
self.outputFeatureDataset = outputFeatureDataset
self.outputFeatureClass = outputFeatureClass
self.processStage = 0
self.stages = ["Testes de conformidade",
"Deleçãoo de Feature Class",
"Cópia de Shapefile",
"Atualização Completa"]
def getProcessStage(self):
return self.stages[self.processStage]
def testGeodatabase(self):
#workspace definido pelo geoprocessor
return self.outputGeodatabase in self.geoprocessorWrapperClass.gp.ListWorkspaces(self.outputGeodatabase,"ALL")
def testFeatureDataset(self):
#adaptando workspace
self.geoprocessorWrapperClass.gp.Workspace += "\" + self.outputGeodatabase
return self.outputFeatureDataset in self.geoprocessorWrapperClass.gp.ListDatasets(self.outputFeatureDataset,"ALL")
def testFeatureClass(self):
#adaptando workpace
self.geoprocessorWrapperClass.gp.Workspace += "\" + self.outputFeatureDataset
return self.outputFeatureClass.gp.Workspace in self.geoprocessorWrapperClass.gp.ListFeatureClasses(self.outputFeatureClass,"ALL")
def testAllObjetcs(self):
if self.testGeodatabase() and self.testFeatureDataset() and self.testFeatureClass():
self.processStage = 1
return True
else:
self.processStage = 0
return False
def deleteFeatureClass(self,featureClass):
try:
self.geoprocessorWrapperClass.gp.Delete_management(featureClass)
except:
print self.geoprocessorWrapperClass.gp.getmessages()
def copyFeatures(self,inputShapefile,outputFeatureClass):
try:
self.geoprocessorWrapperClass.gp.CopyFeatures_management(inputShapefile,outputFeatureClass)
except:
print self.geoprocessorWrapperClass.gp.getmessages()
def updateFeatureClass(self):
try:
if self.testAllObjects:
self.processStage += 1
print self.getProcessStage()
self.deleteFeatureClass(self.outputFeatureClass)
self.processStage += 1
print self.getProcessStage()
self.copyFeatures(self.inputShapefile,self.outputFeatureClass)
self.processStage += 1
print self.getProcessStage()
except:
print self.geoprocessorWrapperClass.gp.getmessages()
Temos os tradicionais import no cabeçalho de nosso arquivo e logo depois o construtor da classe.
Nosso construtor tem os seguintes parâmetros: geoprocessor (um objeto do tipo geoprocessorWrapper), o caminho para o shapefile à ser carregado no banco de dados, o geodatabase de destino, o featureDataset de destino e a FeatureClass de destino.
Você pode ver que construí uma lista de estágios que temos de passar antes de atualizar a FeatureClass. O estágio testes de conformidade vão garantir que os objetos existam no geodatabase e não ocorram erros. Esta etapa pode ser customizada, caso a FeatureClass não exista, crie a mesma, somente importando os dados - também deixo isto para o usuário interessado! Lembre-se que temos de passar um objeto geoprocessorWrapper com um workspace, uma pasta. Neste caso em específico, deve-se passar apenas pastas, pois definimos o geodatabase em outras áreas.
Os testes cuidam da mudança de workspace e asseguram que a featureClass exista. Perceba que todo o trabalho é realizado dentro desta classe, nas funções:
- deleteFeatureClass()
- copyFeatureClass()
Uma função resume todo o processo: updateFeatureClass(). Veja que ela não tem parâmetros, pois usa os parâmetros setados no construtor. À medida que a mesma progride, atualiza o status do processo e informa ao usuário.
Forma de uso:
gp = geoprocessorWrapper.geoprocessorWrapperClass(r"C:",['management']) geoOperation = geodatabaseOperation.geodatabaseOperationClass(gp,r"C:shapefile.shp","teste.mdb","dnpm","dnpm_brasil") geoOperation.updateFeatureClass()
Lembrem-se que o restante do código (buscar o arquivo na net, dezipar, etc) está no post anterior. Como prometi, aqui vai a classe LogHandler.
E ae pessoal? Dúvidas?
Podem ver que o Python dá muito poder ao framework de geoprocessing do ArcGIS e é muito simples.
Um abraço
George
Related posts:
agosto 11th, 2011 - 21:46
Gostaria de fazer um curso em Python voltado p/ BD, trabalho com ArcGis, vcs conhecem algum curso bom?
Desde já agradeço!
[Translate]