Kopieren der ArcSDE-Geodatabase in eine Datei-Geodatabase mit ArcPy?


9

Ich möchte eine genaue Kopie (Domänen, Feature-Datasets, Feature-Classes usw.) einer SDE-Datenbank in eine Datei-Geodatabase erstellen.

Ich habe verschiedene Möglichkeiten ausprobiert, darunter:

  1. Verwenden des Kopierprozesses (Datenverwaltung)
  2. Erstellen einer neuen GDB und manuelles Kopieren jedes Feature-Datasets aus der SDE
  3. Exportieren eines XML-Arbeitsbereichsdokuments aus der SDE und Importieren in die GDB

Der Copy_managementProzess scheint nicht für das Kopieren einer SDE in eine GDB zu funktionieren, da die Eingabe- und Ausgabedatentypen übereinstimmen müssen.

Das Importieren jedes Feature-Datasets in eine neue GDB könnte wahrscheinlich auch mithilfe von Copy_management automatisiert werden, indem jedes Feature-Dataset durchlaufen wird. Dies scheint jedoch zu Problemen mit einer unvollständigen Kopie zu führen, wenn bei einem der Prozesse ein Fehler aufgetreten ist.

Das Exportieren und Importieren von XML-Arbeitsbereichen scheint zu funktionieren, obwohl dieser Prozess unglaublich große Dateien erstellt, wenn der Prozess in großen Geodatabases verwendet wird.

Gibt es eine einfachere Möglichkeit, den Inhalt und das Schema einer SDE in eine GDB zu kopieren als die genannten Möglichkeiten, die automatisiert werden können?

Wenn nicht, gibt es Gründe, warum die oben genannten Möglichkeiten in diesem Prozess nicht genutzt werden sollten?


Antworten:


5

Die einzige Möglichkeit, eine echte Kopie der Daten (Domänen, Datensätze, Beziehungen usw.) zu erhalten, besteht in der manuellen Methode zum Kopieren und Einfügen im Katalog. ESRI hat uns noch nicht die Möglichkeit gegeben, diese Daten mit einem einzigen Vorgang, der einfach per Skript ausgeführt werden kann, auf andere Weise zu übertragen.

Ich habe einen nächtlichen Prozess, der meine beiden primären SDE-Datenbanken in Datei-Geodatabases für Continuity of Operations kopiert. Auf diese Weise können meine Mitarbeiter im Notfall mit einigen Daten arbeiten, bis mein IT-Shop meine SDE aus dem Backup neu erstellen kann. Nach langem Ausprobieren habe ich beschlossen, dass wir mit den Einschränkungen der Verwendung von FeatureClassToFeatureClass_conversion und TableToTable_conversion leben können , um unsere Daten jede Nacht zu übertragen.

Ja, wir verlieren einen Teil der Funktionalität der Geodatabase, aber sie wird jetzt nachts unbeaufsichtigt ausgeführt und ist sofort einsatzbereit, sobald ich sie erhalte. In meinem Fall ist die einzige Funktionalität, die uns wirklich fehlt (vorausgesetzt, wir arbeiten im Notfallmodus), dass meine Beziehungsklassen unterbrochen sind, weil die Konvertierung die ObjectIDs zurücksetzt, die die beiden Tabellen verbinden.

Bis ESRI uns mehr Optionen bietet, müssen Sie sich ansehen, was Sie im Moment opfern wollen. Zeit und Mühe oder Funktionalität?


Ein XML-Worskspace-Dokument würde nicht funktionieren?
Jyler

8

Ich weiß, dass dieser Beitrag etwas alt ist, aber ich dachte, ich würde meine Antwort teilen, da ich mit dem gleichen Problem konfrontiert war. Das folgende Skript SOLLTE alle Tabellen, Feature-Classes und Beziehungen kopieren, die nicht in einem Dataset enthalten sind, und kopiert auch alle Datasets, einschließlich der Feature-Classes, der Topologie usw. innerhalb des Datasets. Es werden alle Fehler übersprungen, die während des Kopierens auftreten, und es wird weitergearbeitet. Es wird eine Protokolldatei erstellt, die Daten wie die Anzahl der Quell-DB-Elemente und die Anzahl der Zielelemente enthält, damit Sie die Kopie vergleichen können, und es werden auch Fehler protokolliert, auf die sie stößt.

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)   

Ich hatte wirklich viel Glück damit. Ich habe eine SDE-Datenbank in eine Datei-Geodatabase repliziert. Ich habe dieses Skript jedoch nicht zu ausführlich getestet, da es alle meine Anforderungen erfüllt. Ich habe es mit ArcGIS 10.3 getestet. Außerdem war ich in Gesprächen mit jemandem, der dieses Skript verwendet hat, und er stieß auf ein Problem mit einem Fehler beim Kopieren bestimmter Datensätze aufgrund falscher Berechtigungen und leerer Tabellen.

Lemur - warum erstellen Sie Ihre Beziehungen nicht basierend auf einer globalen ID anstelle der Objekt-ID? Dass Sie Ihre Beziehungen erhalten würden. Wenn Sie keine globalen IDs erstellt haben, kann ich es nur empfehlen.

-aktualisieren

Ich habe dem Code etwas mehr Logik hinzugefügt, um fehlerhafte Datenbankverbindungspfade und eine bessere Protokollierung und Fehlerbehandlung zu behandeln:

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

Peter, ich habe das von Ihnen bereitgestellte Skript verwendet und die beiden Variablen unten aktualisiert. Ich erhalte die Fehlermeldung Traceback (letzter Aufruf zuletzt): Datei "ServerPath \\ CopySDEtoGDB.py", Zeile 90, in <module> replicateDatabase (databaseConnection, targetGDB) Datei "ServerPath \\ CopySDEtoGDB.py", Zeile 55, in replicateDatabase datasetList = [arcpy.Describe (a) .name für a in arcpy.ListDatasets ()] TypeError: Das Objekt 'NoneType' ist nicht iterierbar. Gibt es einen Hinweis darauf, was dies bedeutet?
Courtney

Courtney - Es klingt so, als ob ein Tippfehler oder ein kleiner Fehler im Pfad zu Ihrer Datenbankverbindungsvariablen vorliegt. Es wird ein Fehler ausgegeben, weil versucht wird, eine Liste zu durchlaufen, die in Zeile 55 leer ist. Ich konnte den Fehler, den Sie erhalten haben, mithilfe des falschen Pfads in der Variablen "databaseConnection" neu erstellen. Was ist der tatsächliche Pfad, den Sie in der Variablen verwendet haben?
PMK

Wenn ich dies jeden Abend tun wollte, werden vorhandene Funktionen nicht überschrieben? Ich möchte nicht jedes Mal eine neue REA erstellen, wenn ich nur das vorhandene Ziel überschreiben möchte.
NULL.Dude

Peter, wenn die Ziel-GDB existiert, schlägt das Skript fehl
NULL.Dude

2

Ich habe ein Skript ähnlich dem von Peter oben verwendet und hatte viel Glück, obwohl seins besser ist. Wenn Sie die 64-Bit-Python-Geoverarbeitung verwenden und ArcFM über ESRI geladen haben, schlägt dies bei allen Funktionen fehl, die für die Verwendung von ArcFM oder Designer mit einem FEHLER 000260 eingestellt wurden Dies liegt daran, dass Sie 32-Bit-Python verwenden müssen, da das ArcFM-Material sonst nicht ordnungsgemäß lizenziert wird.

Eine ausführlichere Beschreibung der Verwendung von 32-Bit-ArcPy finden Sie in den ersten beiden Kommentaren zu diesem Thread in Exchange

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


Wenn diese beiden Kommentare die Antwort auf diese Frage liefern, sollte ihr Inhalt hier entweder zitiert oder zusammengefasst und nicht nur verlinkt werden - siehe meta.stackexchange.com/questions/225370/…. Wenn Sie bereits eine Zusammenfassung bereitgestellt haben, ändern Sie möglicherweise einfach "Überprüfen" Die ersten beiden Kommentare zu diesem Thread in Exchange "bis" Eine ausführlichere Beschreibung finden Sie in den ersten beiden Kommentaren zu diesem Thread in Exchange ".
PolyGeo

0

Wenn Sie Administratorrechte haben , können Sie einfache Kopie verwenden und Geo-Datenbank Schraubstock Befehle Export oder Import sde zu Datei kehrt einfügen und sich auch hier für weitere Details.


Vielen Dank, Ganeshnarim. Ich möchte den Prozess mit Python automatisieren, damit ein manueller Kopier- / Einfügeprozess in ArcCatalog nicht meinen Anforderungen entspricht. Ich hatte auch nur begrenzten Erfolg mit dieser Methode, da anscheinend (in ArcMap 10.1) beim Kopieren einer SDE einfach ein weiterer Link zu derselben Datenbank erstellt wird (während bei Verwendung derselben Technik für eine Datei oder eine persönliche Geodatabase eine Kopie erstellt würde).
Krausers
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.