Introdução
No blog anterior, apresentamos o processamento em lote com Python no ArcGIS comoProcessamento em lote com Python no ArcGIS e Processamento em lote com Python no ArcGIS - Exemplo de implementação, onde introduzimos o processamento em lote usando ArcPy e Python, mostrando exemplos básicos e padrões de codificação.Desta vez, além de atualizar o padrão de codificação para Python 3.3 ou superior, adicionamos um exemplo de integração com as ferramentas do ArcGIS Pro.
Note que o código explicado neste artigo já foi publicado como um Farmland polygon conversion tools e está disponível como uma amostra do Python toolbox. Por favor, consulte-o.
Padrão de codificação
No artigo anterior, os pontos principais do padrão de codificação foram os três a seguir.1) Função worker: batch_convert
2) Wrapper da função worker: multi_run_batch_convert
* Não é necessário desta vez3) Processamento em lote: exec_batch_convert
No entanto, a partir do Python 3.3, a função starmap da classe Pool do módulo multiprocessing foi adicionada para permitir chamadas com múltiplos argumentos. Portanto, ao usar o ambiente atual do ArcGIS Pro, não é necessário o wrapper da função worker e o código pode ser simplificado.
Então, vamos focar nos pontos centrais do padrão de codificação para processamento em lote baseado em amostras.
Código de amostra (conversão de polígonos agrícolas no formato GeoJSON)
Os dados alvo da conversão são os mesmos do artigo anterior, usando como exemplo os dados "Informações de delimitação agrícola (polígonos)" disponibilizados pelo Ministério da Agricultura, Florestas e Pesca.
* Como a estrutura dos polígonos difere do artigo anterior, a amostra publicada no blog é uma introdução baseada no código que converte os polígonos mais recentes (formato GeoJSON).A amostra desta vez (MP_Farmland_JsonToFeatureClass.py) processa uma das "pastas das prefeituras" após descompactar o ZIP dos polígonos agrícolas.
Após descompactar, há várias "pastas GeoJSON por cidade/distrito/aldeia (extensão json)" sob a "pasta da prefeitura".
Pasta de entrada: pasta da prefeitura contendo arquivos GeoJSON por cidade/distrito/aldeia
Exemplo)
|-2024_02
|-2024_022012.json # GeoJSON por cidade/distrito/aldeia
|-2024_022021.json
|-2024_022039.json
.....
No programa de amostra desta vez, a pasta da prefeitura é usada como pasta de entrada e processada da seguinte forma.
1. Criar um geodatabase baseado em arquivo (FGDB) para cada arquivo por cidade/distrito/aldeia e converter os polígonos agrícolas para feature classes (este processo é executado no processamento em lote)
2. Criar um geodatabase baseado em arquivo (FGDB) para a pasta da prefeitura e mesclar as feature classes por cidade/distrito/aldeia como feature class unificada da prefeitura
3. Excluir as feature classes por cidade/distrito/aldeia
Como resultado final, apenas a feature class Farmland unificada permanece no geodatabase baseado em arquivo (FGDB) da pasta da prefeitura (veja o diagrama abaixo).
Pasta de saída: local onde o geodatabase baseado em arquivo unificado da pasta da prefeitura será criado
Exemplo)
|-2024_02_filegdb
|-2024_022012.gdb # FGDB por cidade/distrito/aldeia será excluído após a mesclagem na pasta da prefeitura
| c_2024_022012
|-2024_022021.gdb
| c_2024_022021
.....
|-2024_02_filegdb.gdb # Geodatabase baseado em arquivo da pasta da prefeitura que armazena as feature classes mescladas por cidade/distrito/aldeia
| Farmland # Nome fixo da feature class (fixado no código)
Agora, vamos focar nos pontos centrais do padrão de codificação relacionados à implementação do processamento em lote.
1) Função worker: batch_convert
Como padrão de codificação, primeiro descrevemos a função worker semelhante ao processamento usual com ArcPy. O ponto importante aqui é que, para corresponder ao processamento no 1º processo, se for necessário acessar a partir de múltiplos processos (múltiplas funções worker), use um geodatabase enterprise ou evite usar o mesmo geodatabase.
def batch_convert(in_jsonfile :str, outws :str) -> str:
'"'
'Processamento executado em 1 processo:',' 1) A escrita para FGDB não pode ser feita em múltiplos processos simultaneamente devido à estrutura',' 1 Arquivo GeoJSON por cidade/distrito/aldeia é convertido para uma feature class dentro do gdb 1cidade_distrito_aldeia.gdb usando a classe FarmlandGeojsonToFeaturesEx'"'
'in_jsonfile : caminho para o arquivo GeoJSON por cidade/distrito/aldeia'
'outws : gdb de saída'
'"'
if not arcpy.Exists(outws):
outfolder = u"{0}".format(os.path.dirname(outws))
foldername= u"{0}".format(os.path.basename(outws))
arcpy.management.CreateFileGDB(outfolder, foldername, "CURRENT")
filename = os.path.basename(in_jsonfile)
in_json_file = os.path.splitext(filename)[0]
newfc = u"c_{0}".format(in_json_file) # Como nomes de arquivos iniciando com números não podem ser alterados diretamente, prefixamos com c_.
# Conversão usando a classe exclusiva FarmlandGeojsonToFeaturesEx
#arcpy.conversion.JSONToFeatures(in_jsonfile, os.path.join(outws, newfc))
convGeojson = FarmlandGeojsonToFeaturesEx()
convGeojson.geojson_to_features(in_jsonfile, os.path.join(outws, newfc))
del convGeojson
return u" Conversão concluída: {0}".format(outws)
2) Wrapper da função worker
Como mencionado acima, não é necessário definir este wrapper ao usar o ambiente atual do ArcGIS Pro.
3) Processamento em lote: exec_batch_convert
Passamos o caminho para pythonw.exe usado para cada processo pythonw.exe usando multiprocessing.set_executable(), e passamos dois argumentos (in_jsonfile, outws) para a função worker como uma lista params.Em seguida, garantimos pool criado com multiprocessing.Pool(cpu_cnt), e especificamos o nome da função (batch_convert) e params usando results = pool.starmap(batch_convert, params). Além disso, quando o processamento nas funções worker termina,
pool.close()
pool.join()
são chamados.
def exec_batch_convert(infolder :str, outfolder :str, cpu_cnt :int):
'''
Processamento em lote:
'''
try:
start = datetime.datetime.now()
arcpy.AddMessage(u"-- Início: MP_Farmland_JSONToFeatureClass --:{0}".format(start))
#a) 各プロセス用の pythonw.exe を設定
python_path = sys.exec_prefix
multiprocessing.set_executable(os.path.join(python_path,'pythonw.exe'))
#multiprocessing.set_executable(os.path.join(python_path,'python.exe')) #CMDプロンプトの画面が起動するので'pythonw.exe'を使う
#b) 各プロセスに渡すパラメータをリスト化
arcpy.AddMessage(u" Convert each GeoJSON files : multiprocessing")
arcpy.env.workspace = infolder
infiles = arcpy.ListFiles("*.json")
params=[]
for infile in infiles:
param1 = os.path.join(infolder,infile) #市区町村のGeoJSONファイル
filename = os.path.basename(infile)
gdbname = u"{0}.gdb".format(os.path.splitext(filename)[0])
param2 = os.path.join(outfolder,gdbname) # 出力する市区町村ファイルジオデータベース
params.append((param1, param2))
if len(infiles) < cpu_cnt: # 処理ファイル数がCPUコアより少ない場合無駄なプロセスを起動不要
cpu_cnt = len(infiles)
pool = multiprocessing.Pool(cpu_cnt) # cpu数分プロセス作成
results = pool.starmap(batch_convert, params) # 割り当てプロセスで順次実行される(Python3.3で追加されたstarmapは複数の引数に対応)
pool.close()
pool.join()
# 各プロセスでの処理結果を出力
for r in results:
arcpy.AddMessage(u"{0}".format(r))
#c) 各プロセスで変換されたフィーチャクラスを都道府県のFGDBへマージしたものを作成("Farmland")
#~省略~
# フィールドエイリアスを設定
#~省略~
# コード値ドメインを設定
#~省略~
#d) マージが終わったので後片付け 各市区町村のFGDBを削除
#~省略~
fin = datetime.datetime.now()
arcpy.AddMessage(u"-- Finish: MP_Farmland_JsonToFeatureClass --:{0}".format(fin))
arcpy.AddMessage(u" Elapsed time:{0}".format(fin-start))
except:
arcpy.AddError(u"Exception:{0}".format(sys.exc_info()[2]))
ジオプロセシングツールへの組み込み
O processamento de conversão do polígono agrícola no formato GeoJSON termina com o código acima, então a seguir,Caixa de ferramentas Python explicarei a parte da chamada da caixa de ferramentas geoprocessing definida em.
Na caixa de ferramentas Python, como está descrito na ajuda "O que é uma caixa de ferramentas Python?", as caixas de ferramentas geoprocessing e geoprocessing tools são definidas como classes.
1) Definição da caixa de ferramentas e adição da ferramenta
Definimos duas ferramentas geoprocessing, class AgrilandJsonConvTool e class AgrilandShpConvTool, e as adicionamos na inicialização da class Toolbox como
self.tools = [AgrilandJsonConvTool, AgrilandShpConvTool]
.
# Importação do módulo para suporte a multiprocessamento
from MP_Farmland_JsonToFeatureClass import exec_batch_convert as exec_batch_json_convert
from MP_Farmland_ShapefileToFeatureClass import exec_batch_convert as exec_batch_shp_convert
# Definição da caixa de ferramentas Python
class Toolbox:
def __init__(self):
self.label = "Ferramenta de conversão de polígono agrícola - Caixa de ferramentas de exemplo"
self.alias = ""
self.tools = [AgrilandJsonConvTool, AgrilandShpConvTool]
# Definição das ferramentas geoprocessing individuais
class AgrilandJsonConvTool:
# ~omissão~
class AgrilandShpConvTool:
# ~omissão~
2) Definição da ferramenta
Cada ferramenta geoprocessing deve pelo menos implementar __init__, getParameterInfo e execute para funcionar no ArcGIS Pro como ferramenta geoprocessing.
Neste ponto, o execute apenas chama exec_batch_convert definido no arquivo MP_Farmland_JsonToFeatureClass.py (como adicionamos uma função com o mesmo nome para shapefile, usamos alias exec_batch_json_convert na importação).
class AgrilandJsonConvTool:
def __init__(self):
self.label = "01_Multiprocess_Sample_Ferramenta de conversão de polígono agrícola (formato GeoJSON)"
self.description = ""
def getParameterInfo(self):
param0 = arcpy.Parameter(
displayName="Pasta de entrada (pasta da prefeitura após descompactar)",
name="input_folder",
datatype="DEFolder",
parameterType="Required",
direction="Input")
# ~omissão~
params = [param0, param1, param2]
return params
def execute(self, parameters, messages):
infolder = parameters[0].valueAsText
outfolder = parameters[1].valueAsText
cpu_cnt = int(parameters[2].valueAsText)
exec_batch_json_convert(infolder, outfolder, cpu_cnt)
return
3) Tela de execução
Esta é a tela de execução real da "Farmland polygon conversion tools".
Observação (conversão do arquivo GeoJSON)
Para converter arquivos GeoJSON no ArcGIS Pro, normalmente se usa "JSON → Features (JSON To Features)", mas devido às limitações abaixo, desta vez respondemos com nossa própria classe (class FarmlandGeojsonToFeaturesEx).
- O geometry é definido como PolygonZ.
- O tipo do campo é decidido automaticamente e pode ser necessário converter o tipo depois.
- A ferramenta ainda não suporta definição do código CRS do geometry do polígono agrícola.
Resumo
Com base no processamento multiprocess em ArcPy e Python que publiquei anteriormente em meu blog,
- atualizei o padrão para codificação em Python 3.3 ou superior.
- Adicionei um exemplo de integração para a caixa de ferramentas geoprocessing do ArcGIS Pro chamada "Farmland polygon conversion tools" que criei.