ArcPy コードまとめ

ArcGIS

面倒なので ArcGIS Server のセットアップを ArcPy で自動化しました。
使える部品を紹介していきます。

スポンサーリンク

ArcPyの環境構築

ArcGIS Desktopを入れます。

ArcPyの実行

例えば ArcGIS Desktop 10.5 をインストールし、Python をデフォルト設定でインストールした場合は以下のようになります。

C:\Python27\ArcGIS10.5\python.exe -B E:\Scripts\sample.py

-B で .cpy ファイルを作らないようにしています。

Arc Catalog にデータベース接続を追加する

  • out_dir、file_name で接続ファイルのパスとファイル名を指定します。
  • db_platform でデータベースの種類を指定します(SQLServer、Oracle、…)
  • account_authentication で認証方式を指定します。
  • DATABASE_AUTH: DB認証
  • OPERATING_SYSTEM_AUTH: OS認証
  • save_user_pass でユーザー名とパスワードを接続ファイルに保存するかどうかを指定します。
  • SAVE_USERNAME: 保存する
  • DO_NOT_SAVE_USERNAME: 保存しない
import arcpy

out_dir = r'C:\Users\someone\AppData\Roaming\ESRI\Desktop10.5\ArcCatalog'
file_name = 'db.sde'
db_platform = 'SQL_SERVER'
instance = 'SAMPLE'
account_authentication = 'DATABASE_AUTH'
user_name = 'user'
user_pass = 'pass'
save_user_pass = 'SAVE_USERNAME'
db_name = 'TEST_DB'

arcpy.CreateDatabaseConnection_management(out_dir,
                                          file_name,
                                          db_platform,
                                          instance,
                                          account_authentication,
                                          user_name,
                                          user_pass,
                                          save_user_pass,
                                          db_name)

参考

データベース接続の作成 (Create Database Connection)—ヘルプ | ArcGIS for Desktop
データベースまたは、エンタープライズ、ワークグループ、デスクトップ ジオデータベースへの接続ファイルを作成するための ArcGIS ジオプロセシング ツールです。

Arc Catalog に ArcGIS Server の接続を追加する

  • gisserver_connection_type で接続の設定をします。
  • USER_GIS_SERVICES: GISサービスを使用する
  • PUBLISH_GIS_SERVICES: GISサービスを公開する
  • ADMINISTER_GIS_SERVICES: GISサービスを管理する
  • out_dir、file_name で接続ファイルのパスとファイル名を指定します。
  • save_user_pass でユーザー名とパスワードを接続ファイルに保存するかどうかを指定します。
  • SAVE_USERNAME: 保存する
  • DO_NOT_SAVE_USERNAME: 保存しない
import arcpy

gisserver_connection_type = 'ADMINISTER_GIS_SERVICES'
out_dir = r'C:\Users\someone\AppData\Roaming\ESRI\Desktop10.5\ArcCatalog'
file_name = 'arcgisserverconn.ags'
arcgisserver_url = 'http://server:6080/arcgis/admin'
server_type = 'ARCGIS_SERVER'
use_arcgis_desktop_staging_folder = False
staging_folder_path = out_dir
user_name = 'user'
user_pass = 'pass'
save_user_pass = 'SAVE_USERNAME'

arcpy.mapping.CreateGISServerConnectionFile(gisserver_connection_type,
                                            out_dir,
                                            file_name,
                                            arcgisserver_url,
                                            server_type,
                                            use_arcgis_desktop_staging_folder,
                                            staging_folder_path,
                                            user_name,
                                            user_pass,
                                            save_username_password)

参考

CreateGISServerConnectionFile—Help | ArcGIS for Desktop
ArcPy function to create a GIS Server Connection file.

ArcGIS Serverのデータストアにデータベースを追加する

  • server_connection_file_full_pathでArcGIS Serverの接続ファイル(.ags)のフルパスを指定する.
  • datastore_typeでデータストアの形式を指定する.
  • DATABASE: データベース
  • FOLDER: フォルダー
  • connection_nameで接続に名前を付ける.
  • db_connection_file_full_pathでデータベース接続ファイル(.sde)のフルパスを指定する.
import arcpy

server_connection_file_full_path = r'C:\Users\someone\AppData\Roaming\ESRI\Desktop10.5\ArcCatalog\arcgisserverconn.ags'
datastore_type = 'DATABASE'
connection_name = 'TEST_DB'
db_connection_file_full_path = r'C:\Users\someone\AppData\Roaming\ESRI\Desktop10.5\ArcCatalog\db.sde'

arcpy.AddDataStoreItem(server_connection_file_full_path, 
                       datastore_type, 
                       conn_name, 
                       db_connection_file_full_path, 
                       db_connection_file_full_path)

参考

AddDataStoreItem—ArcGIS Pro | ドキュメント
Registers a folder or database with an ArcGIS Server site.

mxd ファイルのデータソースを修正する

DBサーバーのリプレースに伴い、データソースを修正する必要がありました。
GUIでやるのは超めんどくさいので ArcPy で自動化しました。

下のスクリプトでは念のため編集前の mxd のバックアップを取っています。

import arcpy
import os

base_dir = r'E:\MXD'
backup_dir = os.path.join(base_dir, 'backup')
modified_dir = os.path.join(base_dir, 'modified')
mxd_files = ['a.mxd', 'b.mxd', 'c.mxd', 'd.mxd', 'e.mxd']
old_sde = r'C:\Users\someone\AppData\Roaming\ESRI\Desktop10.1\ArcCatalog\old_db.sde'
new_sde = r'C:\Users\someone\AppData\Roaming\ESRI\Desktop10.5\ArcCatalog\db.sde'

for f in mxd_files:
    file_full_path = os.path.join(c.base_dir, f)
    # バックアップを取る
    shutil.copy(file_full_path, backup_dir)
    # mxdファイルを開いてデータソースを付け替える
    mxd = arcpy.mapping.MapDocument(file_full_path)
    mxd.findAndReplaceWorkspacePaths(old_sde, new_sde)
    # mxdファイルを別ファイルとして保存する
    modified_file_path = os.path.join(modified_dir, f)
    mxd.saveACopy(modified_file_path)
    del mxd

参考

Updating and fixing data sources with arcpy.mapping—Help | ArcGIS for Desktop
You can update and fix data sources with arcpy.mapping.

ArcGIS Serverのサービスを公開する

いちいち 1 個ずつ mxd ファイル開いてサービスを公開するのが辛いので ArcPy で自動化しました。

デフォルトで公開する

デフォルトの設定でサービスを公開する場合は以下になります。
流れは「分析してドラフトサービスを作成する→ドラフトサービスからサービス定義を作成する→サービス定義からサービスを公開する」です。

import arcpy
import os

mxd_dir = r'E:\MXD'
mxd_files = ['a.mxd', 'b.mxd', 'c.mxd', 'd.mxd', 'e.mxd']
sddraft_dir = r'E:\MXD\SDDRAFT'
sd_dir = r'E:\MXD\SD'
server_type = 'ARCGIS_SERVER'
server_connection_file_full_path = r'C:\Users\someone\AppData\Roaming\ESRI\Desktop10.5\ArcCatalog\arcgisserverconn.ags'

for mxd_file in mxd_files:
    mapDoc = arcpy.mapping.MapDocument(os.path.join(c.mxd_dir, mxd_file))
    service_name = mxd_file.split('.mxd')[0]
    sddraft = os.path.join(sddraft_dir, '{0}.sddraft'.format(service_name))
    sd = os.path.join(sd_dir, '{0}.sd'.format(service_name))
    summary = ''
    tags = ''

    # 分析してドラフトサービスを作成する.
    analysis = arcpy.mapping.CreateMapSDDraft(mapDoc, 
                                              sddraft, 
                                              service_name, 
                                              server_type,
                                              server_connection_file_full_path, 
                                              True, 
                                              None, 
                                              summary, 
                                              tags)

    # 分析結果にエラーが無ければサービスを公開する.
    if analysis['errors'] == {}:
        # ドラフトサービスからサービス定義を作成する.
        arcpy.StageService_server(sddraft, sd)
        # サービス定義からサービスを公開する.
        arcpy.UploadServiceDefinition_server(sd, server_connection_file_full_path)
    else: 
        # 分析結果にエラーがあったら表示する.
        print(analysis['errors'])

ドラフトサービスを修正してサービスを公開する

例えば KML を無効にして Feature Access を有効にする場合は以下の通りです。
ドラフトサービスを頑張って編集します。

import arcpy
import os
import codecs
import xml.dom.minidom as DOM

mxd_dir = r'E:\MXD'
mxd_files = ['a.mxd', 'b.mxd', 'c.mxd', 'd.mxd', 'e.mxd']
sddraft_dir = r'E:\MXD\SDDRAFT'
sd_dir = r'E:\MXD\SD'
server_type = 'ARCGIS_SERVER'
server_connection_file_full_path = r'C:\Users\someone\AppData\Roaming\ESRI\Desktop10.5\ArcCatalog\arcgisserverconn.ags'

for mxd_file in mxd_files:
    mapDoc = arcpy.mapping.MapDocument(os.path.join(c.mxd_dir, mxd_file))
    service_name = mxd_file.split('.mxd')[0]
    sddraft = os.path.join(sddraft_dir, '{0}.sddraft'.format(service_name))
    sd = os.path.join(sd_dir, '{0}.sd'.format(service_name))
    summary = ''
    tags = ''

    # 分析してドラフトサービスを作成する.
    analysis = arcpy.mapping.CreateMapSDDraft(mapDoc, 
                                              sddraft, 
                                              service_name, 
                                              server_type,
                                              server_connection_file_full_path, 
                                              True, 
                                              None, 
                                              summary, 
                                              tags)

    # 分析結果にエラーが無ければサービスを公開する.
    if analysis['errors'] == {}:
        # sddraftを読み込む.
        doc = DOM.parse(sddraft)
        # kmlを無効にする.
        services___ = doc.getElementsByTagName('TypeName')
        for service__ in services___:
            if service__.firstChild.data == 'KmlServer':
                service__.parentNode.getElementsByTagName('Enabled')[0].firstChild.data = 'false'
        # Feature Accessを有効にする.
        for service__ in services___:
            if service__.firstChild.data == 'FeatureServer':
                service__.parentNode.getElementsByTagName('Enabled')[0].firstChild.data = 'true'
        # 保存する.
        if os.path.exists(sddraft):
            os.remove(sddraft)
        f = codecs.open(sddraft,"w",'utf-8')
        doc.writexml(f, '', '\t','','utf-8')
        f.close()

        # ドラフトサービスからサービス定義を作成する.
        arcpy.StageService_server(sddraft, sd)
        # サービス定義からサービスを公開する.
        arcpy.UploadServiceDefinition_server(sd, server_connection_file_full_path)
    else: 
        # 分析結果にエラーがあったら表示する.
        print(analysis['errors'])

参考

Specifying map service parameters when publishing with ArcPy?
I publish map services on a ArcGIS server using the typical arcpy script below. I need to better specify some service parameters. For example, the service shoul...
タイトルとURLをコピーしました