ArcPyを使用してArcSDEジオデータベースをファイルジオデータベースにコピーしますか?


9

SDEデータベースの正確なコピー(ドメイン、フィーチャデータセット、フィーチャクラスなど)をファイルジオデータベースに作成したいと考えています。

私は以下を含むいくつかの可能性を試しました:

  1. コピー(データ管理)プロセスの使用
  2. 新しいGDBを作成し、SDEから各フィーチャデータセットを手動でコピーする
  3. SDEからxmlワークスペースドキュメントをエクスポートし、GDBにインポートする

このCopy_managementプロセスは、SDEをGDBにコピーする場合には機能しないようです。これは、入力と出力のデータ型が一致している必要があるためです。

各フィーチャデータセットを新しいGDBにインポートするプロセスは、各フィーチャデータセットを反復処理することで、おそらくCopy_managementを使用して自動化できますが、いずれかのプロセスでエラーが発生した場合、不完全なコピーの問題が発生する可能性があります。

XMLワークスペースのエクスポートとインポートは機能するようですが、このプロセスを大規模なジオデータベースで使用すると、非常に大きなファイルが作成されます。

自動化できる方法で、SDEのコンテンツとスキーマをGDBにコピーする方法として、前述の方法よりも簡単な方法はありますか?

そうでない場合、上記の可能性をこのプロセスで使用すべきでない理由はありますか?


回答:


5

データ(ドメイン、データセット、関係など)の真のコピーを取得できる唯一の方法は、カタログ内で手動のコピーと貼り付けの方法を使用することです。ESRIは、簡単にスクリプト化できる単一の操作で、他の方法でこのデータを転送する機能をまだ提供していません。

2つの主要なSDEデータベースを継続的な運用のためにファイルジオデータベースにコピーする夜間プロセスがあります。これは、緊急事態が発生した場合に、ITショップがバックアップからSDEを再構築できるようになるまで、スタッフがデータを処理できるようにするためです。多くの試行錯誤の後、FeatureClassToFeatureClass_conversionTableToTable_conversionを使用してデータを毎晩転送するという制限に我慢できると判断しました。

はい、ジオデータベースの一部の機能が失われましたが、今では夜間に無人で実行され、入手したらすぐに使用できます。私の場合、(緊急モードで動作していると仮定して)本当に欠けている唯一の機能は、2つのテーブルをリンクするObjectIDが変換によってリセットされるため、リレーションシップクラスが壊れていることです。

ESRIがより多くのオプションを提供するまでは、現時点で何を犠牲にしても構わないと思っています。時間と労力または機能?


xml worskspace docは機能しませんか?
Jyler 2016

8

私はこの投稿が少し古いことを知っていますが、同じ問題に直面したので、私は答えを共有します。次のスクリプトは、データセット内にないすべてのテーブル、フィーチャクラス、および関係をコピーする必要があります(SHOULD)。また、データセット内のフィーチャクラス、トポロジなどを含むすべてのデータセットをコピーします。コピー中のエラーをスキップして続行します。コピー元を比較できるように、ソースDBアイテム数や宛先アイテム数などのデータを含むログファイルを生成し、発生したエラーもログに記録します。

import arcpy, os, shutil, time
import logging as log
from datetime import datetime

def formatTime(x):
    minutes, seconds_rem = divmod(x, 60)
    if minutes >= 60:
        hours, minutes_rem = divmod(minutes, 60)
        return "%02d:%02d:%02d" % (hours, minutes_rem, seconds_rem)
    else:
        minutes, seconds_rem = divmod(x, 60)
        return "00:%02d:%02d" % (minutes, seconds_rem)

def getDatabaseItemCount(workspace):
    arcpy.env.workspace = workspace
    feature_classes = []
    for dirpath, dirnames, filenames in arcpy.da.Walk(workspace,datatype="Any",type="Any"):
        for filename in filenames:
            feature_classes.append(os.path.join(dirpath, filename))
    return feature_classes, len(feature_classes)

def replicateDatabase(dbConnection, targetGDB):
    startTime = time.time()

    featSDE,cntSDE = getDatabaseItemCount(dbConnection)
    featGDB,cntGDB = getDatabaseItemCount(targetGDB)

    now = datetime.now()
    logName = now.strftime("SDE_REPLICATE_SCRIPT_%Y-%m-%d_%H-%M-%S.log")
    log.basicConfig(datefmt='%m/%d/%Y %I:%M:%S %p', format='%(asctime)s %(message)s',\
    filename=logName,level=log.INFO)

    print "Old Target Geodatabase: %s -- Feature Count: %s" %(targetGDB, cntGDB)
    log.info("Old Target Geodatabase: %s -- Feature Count: %s" %(targetGDB, cntGDB))
    print "Geodatabase being copied: %s -- Feature Count: %s" %(dbConnection, cntSDE)
    log.info("Geodatabase being copied: %s -- Feature Count: %s" %(dbConnection, cntSDE))

    arcpy.env.workspace = dbConnection

    #deletes old targetGDB
    try:
        shutil.rmtree(targetGDB)
        print "Deleted Old %s" %(os.path.split(targetGDB)[-1])
        log.info("Deleted Old %s" %(os.path.split(targetGDB)[-1]))
    except Exception as e:
        print e
        log.info(e)

    #creates a new targetGDB
    GDB_Path, GDB_Name = os.path.split(targetGDB)
    print "Now Creating New %s" %(GDB_Name)
    log.info("Now Creating New %s" %(GDB_Name))
    arcpy.CreateFileGDB_management(GDB_Path, GDB_Name)

    datasetList = [arcpy.Describe(a).name for a in arcpy.ListDatasets()]
    featureClasses = [arcpy.Describe(a).name for a in arcpy.ListFeatureClasses()]
    tables = [arcpy.Describe(a).name for a in arcpy.ListTables()]

    #Compiles a list of the previous three lists to iterate over
    allDbData = datasetList + featureClasses + tables

    for sourcePath in allDbData:
        targetName = sourcePath.split('.')[-1]
        targetPath = os.path.join(targetGDB, targetName)
        if arcpy.Exists(targetPath)==False:
            try:
                print "Atempting to Copy %s to %s" %(targetName, targetPath)
                log.info("Atempting to Copy %s to %s" %(targetName, targetPath))
                arcpy.Copy_management(sourcePath, targetPath)
                print "Finished copying %s to %s" %(targetName, targetPath)
                log.info("Finished copying %s to %s" %(targetName, targetPath))
            except Exception as e:
                print "Unable to copy %s to %s" %(targetName, targetPath)
                print e
                log.info("Unable to copy %s to %s" %(targetName, targetPath))
                log.info(e)
        else:
            print "%s already exists....skipping....." %(targetName)
            log.info("%s already exists....skipping....." %(targetName))
    featGDB,cntGDB = getDatabaseItemCount(targetGDB)
    print "Completed replication of %s -- Feature Count: %s" %(dbConnection, cntGDB)
    log.info("Completed replication of %s -- Feature Count: %s" %(dbConnection, cntGDB))
    totalTime = (time.time() - startTime)
    totalTime = formatTime(totalTime)
    log.info("Script Run Time: %s" %(totalTime))

if __name__== "__main__":
    databaseConnection = r"YOUR_SDE_CONNECTION"
    targetGDB = "DESTINATION_PATH\\SDE_Replicated.gdb"
    replicateDatabase(databaseConnection, targetGDB)   

私はこれで本当に幸運でした。SDEデータベースをファイルジオデータベースに複製していました。このスクリプトは私のニーズをすべて満たしているので、このスクリプトのテストはあまり行いませんでした。ArcGIS 10.3を使用してテストしました。また、注意すべき点の1つは、このスクリプトを使用した人と話していたところ、不適切な権限と空のテーブルが原因で、特定のデータセットをコピーするときにエラーが発生するという問題が発生しました。

キツネザル-オブジェクトIDではなくグローバルIDに基づいて関係を作成しませんか?あなたの関係が維持されること。グローバルIDを作成していない場合は、お勧めします。

-更新

不正なデータベース接続パスを処理し、ロギングとエラー処理を改善するために、コードにもう少しロジックを追加しました。

import time, os, datetime, sys, logging, logging.handlers, shutil
import arcpy

########################## user defined functions ##############################

def getDatabaseItemCount(workspace):
    log = logging.getLogger("script_log")
    """returns the item count in provided database"""
    arcpy.env.workspace = workspace
    feature_classes = []
    log.info("Compiling a list of items in {0} and getting count.".format(workspace))
    for dirpath, dirnames, filenames in arcpy.da.Walk(workspace,datatype="Any",type="Any"):
        for filename in filenames:
            feature_classes.append(os.path.join(dirpath, filename))
    log.info("There are a total of {0} items in the database".format(len(feature_classes)))
    return feature_classes, len(feature_classes)

def replicateDatabase(dbConnection, targetGDB):
    log = logging.getLogger("script_log")
    startTime = time.time()

    if arcpy.Exists(dbConnection):
        featSDE,cntSDE = getDatabaseItemCount(dbConnection)
        log.info("Geodatabase being copied: %s -- Feature Count: %s" %(dbConnection, cntSDE))
        if arcpy.Exists(targetGDB):
            featGDB,cntGDB = getDatabaseItemCount(targetGDB)
            log.info("Old Target Geodatabase: %s -- Feature Count: %s" %(targetGDB, cntGDB))
            try:
                shutil.rmtree(targetGDB)
                log.info("Deleted Old %s" %(os.path.split(targetGDB)[-1]))
            except Exception as e:
                log.info(e)

        GDB_Path, GDB_Name = os.path.split(targetGDB)
        log.info("Now Creating New %s" %(GDB_Name))
        arcpy.CreateFileGDB_management(GDB_Path, GDB_Name)

        arcpy.env.workspace = dbConnection

        try:
            datasetList = [arcpy.Describe(a).name for a in arcpy.ListDatasets()]
        except Exception, e:
            datasetList = []
            log.info(e)
        try:
            featureClasses = [arcpy.Describe(a).name for a in arcpy.ListFeatureClasses()]
        except Exception, e:
            featureClasses = []
            log.info(e)
        try:
            tables = [arcpy.Describe(a).name for a in arcpy.ListTables()]
        except Exception, e:
            tables = []
            log.info(e)

        #Compiles a list of the previous three lists to iterate over
        allDbData = datasetList + featureClasses + tables

        for sourcePath in allDbData:
            targetName = sourcePath.split('.')[-1]
            targetPath = os.path.join(targetGDB, targetName)
            if not arcpy.Exists(targetPath):
                try:
                    log.info("Atempting to Copy %s to %s" %(targetName, targetPath))
                    arcpy.Copy_management(sourcePath, targetPath)
                    log.info("Finished copying %s to %s" %(targetName, targetPath))
                except Exception as e:
                    log.info("Unable to copy %s to %s" %(targetName, targetPath))
                    log.info(e)
            else:
                log.info("%s already exists....skipping....." %(targetName))

        featGDB,cntGDB = getDatabaseItemCount(targetGDB)
        log.info("Completed replication of %s -- Feature Count: %s" %(dbConnection, cntGDB))

    else:
        log.info("{0} does not exist or is not supported! \
        Please check the database path and try again.".format(dbConnection))

#####################################################################################

def formatTime(x):
    minutes, seconds_rem = divmod(x, 60)
    if minutes >= 60:
        hours, minutes_rem = divmod(minutes, 60)
        return "%02d:%02d:%02d" % (hours, minutes_rem, seconds_rem)
    else:
        minutes, seconds_rem = divmod(x, 60)
        return "00:%02d:%02d" % (minutes, seconds_rem)

if __name__ == "__main__":
    startTime = time.time()
    now = datetime.datetime.now()

    ############################### user variables #################################
    '''change these variables to the location of the database being copied, the target 
    database location and where you want the log to be stored'''

    logPath = ""
    databaseConnection = "path_to_sde_or_gdb_database"
    targetGDB = "apth_to_replicated_gdb\\Replicated.gdb"

    ############################### logging items ###################################
    # Make a global logging object.
    logName = os.path.join(logPath,(now.strftime("%Y-%m-%d_%H-%M.log")))

    log = logging.getLogger("script_log")
    log.setLevel(logging.INFO)

    h1 = logging.FileHandler(logName)
    h2 = logging.StreamHandler()

    f = logging.Formatter("[%(levelname)s] [%(asctime)s] [%(lineno)d] - %(message)s",'%m/%d/%Y %I:%M:%S %p')

    h1.setFormatter(f)
    h2.setFormatter(f)

    h1.setLevel(logging.INFO)
    h2.setLevel(logging.INFO)

    log.addHandler(h1)
    log.addHandler(h2)

    log.info('Script: {0}'.format(os.path.basename(sys.argv[0])))

    try:
        ########################## function calls ######################################

        replicateDatabase(databaseConnection, targetGDB)

        ################################################################################
    except Exception, e:
        log.exception(e)

    totalTime = formatTime((time.time() - startTime))
    log.info('--------------------------------------------------')
    log.info("Script Completed After: {0}".format(totalTime))
    log.info('--------------------------------------------------')

ピーター、あなたが提供したスクリプトを使用し、下部にある2つの変数を更新しました。エラー「トレースバック(最新の呼び出しは最後)」:ファイル「ServerPath \\ CopySDEtoGDB.py」、90行目、<module> replicateDatabase(databaseConnection、targetGDB)ファイル「ServerPath \\ CopySDEtoGDB.py」、55行目replicateDatabase datasetList = [arcpy.Describe(a).name in a arcpy.ListDatasets()] TypeError: 'NoneType'オブジェクトは反復可能ではありませんこれが意味する手掛かりはありますか?
コートニー

コートニー-データベース接続変数へのパスにタイプミスまたはわずかなエラーがあるようです。55行目で空のリストを繰り返し処理しようとしているため、エラーがスローされています。「databaseConnection」変数の誤ったパスを使用して、取得したエラーを再現できました。変数で使用した実際のパスは何ですか?
PMK 2015年

これを毎晩実行したい場合、既存の機能は上書きされませんか?既存のターゲットを上書きするたびに新しいFGDを作成したくありません。
NULL。デュードは

ターゲットGDBは、スクリプトが失敗した場合に存在するピーター
NULL.Dude

2

私は上記のピーターに似たスクリプトを使用し、幸運がありましたが、彼の方が優れています。64ビットのPythonジオプロセシングを使用していて、Esriの上にArcFMがロードされている場合、ArcFMまたはDesignerを使用するように設定されているすべての機能で失敗し、エラー000260が発生します。これは、32ビットのpythonを使用する必要があるためです。そうしないと、ArcFMのものは適切にライセンスされません。

32ビットArcPyの使用の詳細については、Exchangeのこのスレッドの最初の2つのコメントを参照してください。

https://infrastructurecommunity.schneider-electric.com/docs/DOC-2563


これらの2つのコメントがこの質問への回答を提供する場合、それらの内容はここに引用または要約するだけでなく、リンクする 必要があります-meta.stackexchange.com/questions/225370/を参照してください。 「Exchangeのこのスレッドの最初の2つのコメント」から「詳細な説明については、Exchangeのこのスレッドの最初の2つのコメントを参照してください」に。
PolyGeo

0

管理者権限がある場合は、単純なコピーアンドペーストコマンドを使用して、sdeをファイルジオデータベースにエクスポートまたはインポートすることもできます。詳細については、こちらをご覧ください。


ありがとうGaneshnarim-Pythonを使用してプロセスを自動化したいので、ArcCatalogでの手動のコピー/貼り付けプロセスは私のニーズに適合しません。(ArcMap 10.1では)SDEをコピーすると、同じデータベースへの別のリンクが作成されるように見えるため、この方法でも成功は限られていました(この同じ手法がファイルまたはパーソナルジオデータベースで使用された場合、コピーが作成されます)。
Krausers 2013
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.