ArcPy를 사용하여 ArcSDE 지오 데이터베이스를 파일 지오 데이터베이스로 복사 하시겠습니까?


9

SDE 데이터베이스의 정확한 사본 (도메인, 기능 데이터 세트, 기능 클래스 등)을 파일 지오 데이터베이스에 만들고 싶습니다.

나는 여러 가지 가능성을 시도했다.

  1. 복사 (데이터 관리) 프로세스 사용
  2. 새 GDB 생성 및 SDE에서 각 기능 데이터 세트 수동 복사
  3. SDE에서 xml 작업 공간 문서 내보내기 및 GDB로 가져 오기

Copy_management입력 및 출력 데이터 형식이 일치해야하기 때문에이하는 GDB에 SDE를 복사하는 일을하는 것처럼 프로세스가 보이지 않는다.

각 기능 데이터 세트를 새 GDB로 가져 오는 프로세스는 아마도 각 기능 데이터 세트를 반복하여 Copy_management를 사용하여 자동화 할 수 있지만 프로세스 중 하나에 오류가있는 경우 불완전한 사본의 문제점이 발생할 수 있습니다.

xml 작업 공간 내보내기 및 가져 오기가 작동하는 것처럼 보이지만이 프로세스는 대규모 지오 데이터베이스에서 프로세스를 사용할 때 엄청나게 큰 파일을 생성합니다.

자동화 된 방법으로 SDE의 내용과 스키마를 언급 된 방법보다 GDB에 복사하는보다 간단한 방법이 있습니까?

그렇지 않은 경우 위의 가능성을이 프로세스에서 사용하지 않아야하는 이유가 있습니까?


답변:


5

데이터의 실제 복사본 (도메인, 데이터 집합, 관계 등)을 얻을 수있는 유일한 방법은 카탈로그 내에서 수동 복사 및 붙여 넣기 방법을 사용하는 것입니다. ESRI는 아직 쉽게 스크립팅 할 수있는 단일 작업으로 다른 방법으로이 데이터를 전송할 수있는 기능을 제공하지 않았습니다.

연속 작업을 위해 두 개의 기본 SDE 데이터베이스를 지리 데이터베이스에 복사하는 야간 프로세스가 있습니다. 응급 상황이 발생하면 IT 직원이 백업을 통해 SDE를 재 구축 할 수있을 때까지 직원이 처리 할 데이터가 있습니다. 많은 시행 착오 끝에 FeatureClassToFeatureClass_conversionTableToTable_conversion 을 사용하여 매일 밤 데이터를 전송 하는 데 한계가 있습니다 .

예, 우리는 지오 데이터베이스의 일부 기능을 잃어 버렸지 만 이제는 밤에 무인 상태로 실행되며 내가 도착하자마자 갈 준비가되었습니다. 필자의 경우 우리가 실제로 놓친 기능 (비상 모드에서 작동한다고 가정)은 변환이 두 테이블을 연결하는 ObjectID를 재설정하기 때문에 관계 클래스가 손상되었다는 것입니다.

ESRI가 더 많은 옵션을 제공 할 때까지 현재 무엇을 기꺼이 희생해야하는지 살펴 봐야합니다. 시간과 노력 또는 기능?


xml worskspace 문서가 작동하지 않습니까?
Jyler

8

나는이 게시물이 조금 오래되었다는 것을 알고 있지만 같은 문제에 직면했기 때문에 대답을 공유 할 것입니다. 다음 스크립트는 데이터 세트에없는 모든 테이블, 피처 클래스 및 관계를 복사해야하며 데이터 세트 내의 피처 클래스, 토폴로지 등을 포함한 모든 데이터 세트를 복사해야합니다. 사본이 계속 진행되는 동안 오류를 건너 뜁니다. 소스 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을 사용하여 테스트했습니다. 또한 한 가지 주목할 점은이 스크립트를 사용하는 사람과 대화 중이며 권한이 잘못되고 테이블이 비어있어 특정 데이터 세트를 복사하는 동안 오류가 발생했습니다.

여우 원숭이-객체 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('--------------------------------------------------')

피터, 나는 당신이 제공 한 스크립트를 사용하고 하단에 두 변수를 업데이트했습니다. 오류 추적이 발생합니다 (가장 최근 호출) : <모듈> replicateDatabase (databaseConnection, targetGDB)의 "ServerPath \\ CopySDEtoGDB.py"파일, 90 행, "ServerPath \\ CopySDEtoGDB.py"파일, 55 행 replicateDatabase datasetList = [arpy.ListDatasets ()의 arcpy.Describe (a) .name] TypeError : 'NoneType'객체를 반복 할 수 없습니다. 이것이 무엇을 의미하는 단서가 있습니까?
코트니

Courtney-데이터베이스 연결 변수 경로에 오타 나 약간의 오류가있는 것 같습니다. 55 행에서 비어있는 목록을 반복하려고하기 때문에 오류가 발생합니다. "databaseConnection"변수에 잘못된 경로를 사용하여 발생한 오류를 다시 작성할 수있었습니다. 변수에 사용한 실제 경로는 무엇입니까?
PMK

매일 밤이 작업을 수행하려는 경우 기존 기능을 덮어 쓰지 않습니까? 기존 대상을 덮어 쓰려고 할 때마다 새 FGD를 만들고 싶지 않습니다.
NULL. Dude '12

대상 GDB가 존재하는 경우 스크립트 실패
NULL.Dude

2

Peter의 위와 비슷한 스크립트를 사용했으며 행운이 있었지만 그의 것이 더 낫습니다. 64 비트 파이썬 지오 프로세싱을 사용하고 있고 ESRI 위에 ArcFM이로드되어 있으면 ArcFM 또는 Designer를 ERROR 000260과 함께 사용하도록 설정된 모든 기능에서 실패합니다. 32 비트 파이썬을 사용해야하거나 ArcFM 항목이 올바르게 라이센스되지 않기 때문입니다.

32 비트 ArcPy 사용에 대한 자세한 내용은 Exchange에서이 스레드에 대한 처음 두 개의 설명을 참조하십시오.

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


이 두 가지 의견이이 질문에 대한 답변을 제공하는 경우 해당 내용이 여기에 인용되거나 요약되어 있고 링크되어 있지 않아야합니다. meta.stackexchange.com/questions/225370/… 참조 요약을 이미 제공 한 경우 "Check 자세한 내용은 Exchange에서이 스레드에 대한 처음 두 개의 설명을 참조하십시오. "를 참조하십시오.
PolyGeo

0

관리자 권한이있는 경우 간단한 복사 및 붙여 넣기 명령을 사용하여 sde를 파일 지오 데이터베이스로 내보내거나 가져올 수 있으며 자세한 내용 은 여기 를 참조하십시오.


Thanks Ganeshnarim-Python을 사용하여 프로세스를 자동화하고 싶습니다. 따라서 ArcCatalog의 수동 복사 / 붙여 넣기 프로세스는 내 요구에 맞지 않습니다. SDE를 복사하면 단순히 동일한 데이터베이스에 대한 다른 링크를 만드는 것처럼 보입니다 (ArcMap 10.1에서).
Krausers
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.