Copiando il geodatabase ArcSDE per archiviare il geodatabase usando ArcPy?


9

Vorrei fare una copia esatta (domini, set di dati di funzionalità, classi di funzionalità, ecc.) Di un database SDE in un geodatabase di file.

Ho provato diverse possibilità, tra cui:

  1. utilizzando il processo Copia (Gestione dati)
  2. creando un nuovo GDB e copiando manualmente ogni set di dati di funzionalità dall'SDE
  3. esportazione di un documento xml area di lavoro da SDE e importazione in GDB

Il Copy_managementprocesso non sembra funzionare per la copia di un SDE in un GDB, poiché i tipi di dati di input e output devono corrispondere.

Il processo di importazione di ogni set di dati di funzionalità in un nuovo GDB potrebbe probabilmente essere automatizzato utilizzando Copy_management e iterando attraverso ogni set di dati di funzionalità, sebbene ciò possa causare problemi di una copia incompleta in caso di errore con uno dei processi.

L'esportazione e l'importazione di aree di lavoro XML sembra funzionare, sebbene questo processo crei file incredibilmente grandi quando il processo viene utilizzato su geodatabase di grandi dimensioni.

Esiste un modo più semplice per copiare i contenuti e lo schema di un SDE in un GDB rispetto ai modi menzionati, in un modo che può essere automatizzato?

In caso contrario, ci sono dei motivi per cui le suddette possibilità non dovrebbero essere utilizzate in questo processo?


Risposte:


5

L'unico modo per ottenere una copia vera dei dati (domini, set di dati, relazioni, ecc.) È utilizzare il metodo di copia e incolla manuale all'interno del catalogo. ESRI non ci ha ancora dato la possibilità di trasferire questi dati in nessun altro modo con un'unica operazione che può essere facilmente copiata.

Ho un processo notturno che copia i miei due database SDE primari per archiviare geodatabase per la continuità delle operazioni. Questo in modo che in caso di emergenza il mio personale abbia alcuni dati con cui lavorare fino a quando il mio negozio IT può ricostruire il mio SDE dal backup. Dopo molti tentativi ed errori ho deciso possiamo vivere con le limitazioni di utilizzo FeatureClassToFeatureClass_conversion e TableToTable_conversion per trasferire i nostri dati su ogni notte.

Sì, perdiamo alcune delle funzionalità del geodatabase ma ora verrà eseguito incustodito di notte ed è pronto per l'uso non appena lo avrò. Nel mio caso, l'unica funzionalità che ci manca veramente (supponendo che operi in una modalità di emergenza) è che le mie classi di relazione sono interrotte perché la conversione ripristina gli ObjectID che collegano le due tabelle.

Fino a quando ESRI non ci darà più opzioni, dovrai guardare a cosa sei disposto a sacrificare in questo momento; tempo e fatica o funzionalità?


Un documento xml worskspace non funzionerebbe?
Jyler,

8

So che questo post è un po 'vecchio ma ho pensato di condividere la mia risposta da quando ho dovuto affrontare lo stesso problema. Il seguente script DOVREBBE copiare tutte le tabelle, le classi di funzionalità e le relazioni non in un set di dati e copierà anche su tutti i set di dati, comprese le classi di funzionalità, la topologia, ecc. All'interno del set di dati. Ignorerà eventuali errori durante la copia e continuerà. Produrrà un file di registro che contiene dati come il conteggio degli elementi del DB di origine e il conteggio degli elementi di destinazione in modo da poter confrontare la copia e registrerà anche gli errori riscontrati.

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)   

Ho avuto davvero buona fortuna con questo. Stavo replicando un database SDE in un file geodatabase. Non ho eseguito test troppo approfonditi su questo script, poiché ha soddisfatto tutte le mie esigenze. L'ho provato usando ArcGIS 10.3. Inoltre, una cosa da notare, ero in trattative con qualcuno che ha utilizzato questo script e hanno riscontrato un problema con un errore durante la copia di determinati set di dati a causa di autorizzazioni errate e tabelle vuote.

Lemure: perché non creare relazioni basate su un ID globale anziché sull'ID oggetto? Che le tue relazioni sarebbero state preservate. Se non hai creato ID globali, lo consiglio vivamente.

-aggiornare

Ho aggiunto un po 'più di logica al codice per gestire percorsi di connessione al database errati e una migliore registrazione e gestione degli errori:

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, ho usato lo script che hai fornito e ho aggiornato le 2 variabili in fondo. Ricevo un errore Traceback (ultima chiamata più recente): File "ServerPath \\ CopySDEtoGDB.py", linea 90, in <module> replicateDatabase (databaseConnection, targetGDB) File "ServerPath \\ CopySDEtoGDB.py", linea 55, in replicateDatabase datasetList = [arcpy.Describe (a) .name per a in arcpy.ListDatasets ()] TypeError: l'oggetto 'NoneType' non è iterabile Qualche idea di cosa significhi?
Courtney,

Courtney: sembra che ci sia un errore di battitura o un leggero errore nel percorso della variabile di connessione al database. Sta generando un errore perché sta tentando di scorrere su un elenco vuoto alla riga 55. Sono stato in grado di ricreare l'errore che hai riscontrato utilizzando il percorso errato nella variabile "databaseConnection". qual è il percorso effettivo che hai usato nella variabile?
PMK,

Se volessi farlo di notte, non sovrascriverebbe le funzionalità esistenti? Non voglio creare un nuovo FGD ogni volta che voglio solo sovrascrivere il target esistente.
NULL.Dude

Peter, se esiste il GDB target, lo script fallisce
NULL.Dude,

2

Ho usato una sceneggiatura simile a quella di Peter in alto e ho avuto buona fortuna, anche se la sua è migliore. Una cosa da sottolineare che potrebbe far inciampare qualcuno è se stai usando il geoprocessing in pitone a 64 bit e hai ArcFM caricato sopra ESRI, fallirà su tutte le funzionalità che sono state impostate per usare ArcFM o Designer con un ERRORE 000260. Questo è perché è necessario utilizzare Python a 32 bit o le cose ArcFM non saranno autorizzate correttamente.

Per una descrizione più dettagliata dell'uso di ArcPy a 32 bit, vedere i primi due commenti su questo thread in Exchange

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


Se questi due commenti forniscono la risposta a questa domanda, i loro contenuti devono essere citati o riepilogati qui e non semplicemente collegati a - vedi meta.stackexchange.com/questions/225370/… Se hai già fornito un riepilogo, forse cambia "Verifica i primi due commenti su questo thread in Exchange "a" Per una descrizione più dettagliata vedere i primi due commenti su questo thread in Exchange ".
PolyGeo

0

Se si dispone dei privilegi di amministratore, è possibile utilizzare semplici comandi copia e incolla per esportare o importare sde nel file geo-database viceversa e dare un'occhiata qui per maggiori dettagli.


Grazie Ganeshnarim - Vorrei automatizzare il processo usando Python, quindi qualsiasi processo manuale di copia / incolla in ArcCatalog non si adattava alle mie esigenze. Ho avuto anche un successo limitato con questo metodo, poiché sembra che (in ArcMap 10.1) la copia di un SDE crei semplicemente un altro collegamento allo stesso database (mentre se questa stessa tecnica fosse usata su un file o un geodatabase personale, ne verrebbe fatta una copia)
Krausers
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.