Перевірка через ArcPy, чи ArcMap знаходиться в сесії редагування?


11

Я створив кнопку надбудови Python, яка допомагає прискорити робочий процес моїх колег, копіюючи один атрибут класу функцій в інший. Він використовує функцію arcpy.UpdateCursor для оновлення рядка в цільовому класі функцій. Як існує зараз, цей скрипт кнопки може бути запущений незалежно від режиму редагування. Очевидно, що після запуску в сеансі редагування користувач може зупинити редагування та не зберігати зміни, але це не так, коли сценарій працює поза сеансом редагування.

Як я можу додати чек до сценарію, який зупинить запуск сценарію, якщо ArcMap зараз не перебуває в сесії редагування?

Це стосується ArcMap 10 та 10.1


Я також хочу проконсультуватися з іншими користувачами ArcMap, щоб перевірити, що оновлення таблиць зазвичай не дозволено, не перебуваючи в сесії редагування.

То як цей скрипт працює поза сеансом редагування?

Цей сценарій також піднімає ще одне питання щодо, здавалося б, порядкового вибору вибору ArcMap, який просто працює для мене, коли я оновлюю таблицю другого класу зі списку, але це вже інший день.

Ось сценарій, як він працює зараз (без будь-якої реалізації редактора 10.1):

Як додати чек, щоб переконатися, що користувач перебуває в сесії редагування?

def onClick(self):
    #Reference mxd
    mxd = arcpy.mapping.MapDocument("CURRENT")
    #Reference the main Data frame
    mm = arcpy.mapping.ListDataFrames(mxd, "MainMap")[0]
    #Reference the Water System Valve feature class
    waterValves = arcpy.mapping.ListLayers(mxd, "Water System Valve", mm)[0]
    #Reference the fire hydrant feature class
    fireHydrants = arcpy.mapping.ListLayers(mxd, "Water Hydrant", mm)[0]

    #Use the extent of the main DF to select all valves in the current view
    dfAsFeature = arcpy.Polygon(arcpy.Array([mm.extent.lowerLeft, mm.extent.lowerRight, mm.extent.upperRight, mm.extent.upperLeft]), mm.spatialReference)
    arcpy.SelectLayerByLocation_management(waterValves, "WITHIN", dfAsFeature,"", "NEW_SELECTION")

    arcpy.SelectLayerByAttribute_management(waterValves, "SUBSET_SELECTION", "LOCATIONID IS NULL")

    fields = ["LOCATIONID"]

    row, rows = None, None
    rows = arcpy.UpdateCursor(waterValves,fields)
    row = rows.next()
    valveList = []
    append = valveList.append

    #Loop through the valves table to update LocationID
    while row:
        builder = str(row.QSNO)+"-"+ str(row.VALVESEQNO)
        row.setValue("LOCATIONID", builder)
        append(builder)
        rows.updateRow(row)
        row = rows.next()

    del row, rows

    #New selection for fire hydrants
    arcpy.SelectLayerByLocation_management(fireHydrants, "WITHIN", dfAsFeature,"", "NEW_SELECTION")
    arcpy.SelectLayerByAttribute_management(fireHydrants, "SUBSET_SELECTION", "LOCATIONID IS NULL")

    row, rows = None, None
    rows = arcpy.UpdateCursor(fireHydrants,fields)
    row = rows.next()

    #Loop through fire hydrant table to update LocationID
    while row:
        for locID in valveList:
            construct = str(locID) + "-FH"
            #print construct
            row.setValue("LOCATIONID", construct)
            rows.updateRow(row)
            row = rows.next()

    del row, rows, valveList, mxd

Здається, редактор модуля доступу до даних працює незалежно від стандартного редактора. Я вітаю будь-які додаткові ідеї щодо тестування для активного сеансу редагування. -Карл
KarlJr

Чи можете ви надати трохи більше інформації? Що привело вас до такого висновку для тих із нас, хто не вивчив модуль?
Джей Лора

Відповіді:


6

Ось загальна функція, заснована на цій публікації.

Можливо, це трохи кумедніше рішення, ніж рішення ArcObjects, але це впевнено здається набагато менше клопоту! Просте - краще, ніж складне. За винятком випадків, коли цього немає.

Приклад використання:

if CheckEditSession(tbl):
    print("An edit session is currently open.")

код:

def CheckEditSession(lyr):
    """Check for an active edit session on an fc or table.
    Return True of edit session active, else False"""
    edit_session = True
    row1 = None
    try:
        # attempt to open two cursors on the input
        # this generates a RuntimeError if no edit session is active
        OID = arcpy.Describe(lyr).OIDFieldName
        with arcpy.da.UpdateCursor(lyr, OID) as rows:
            row = next(rows)
            with arcpy.da.UpdateCursor(lyr, OID) as rows2:
                row2 = next(rows2)
    except RuntimeError as e:
        if e.message == "workspace already in transaction mode":
            # this error means that no edit session is active
            edit_session = False
        else:
            # we have some other error going on, report it
            raise
    return edit_session

+1 Приємна концепція, проте ОП хоче зупинити, якщо не на сесії редагування, і продовжити, якщо вона знаходиться в сесії редагування. Здається, ваша відповідь робить протилежне. Можливо, не знадобиться багато, щоб це розвернути.
Midavalo

ОП вже вирішила свою проблему, ця посада - це лише обмерзання з загальнокориснішою функцією. Я змінив свій приклад, щоб зрозуміти, як функція використовується.
Ціна Кертіса

4

Моє рішення цієї проблеми було використовувати розширення, доступні для панелі інструментів Arcpy Addin. Я додав розширення, яке прослуховує початок або закінчення сеансу редагування. У мене всі кнопки на панелі встановлені на: self.enable = Неправильно ", щоб почати з, а потім ці кнопки або активувати, або відключати, запускаючи або зупиняючи сеанс редагування.

class Active_Edit_Session(object):
"""Implementation for NEZ_EDITS_addin.Listen_for_Edit_Session (Extension)"""
def __init__(self):
    self.enabled = True
def onStartEditing(self):
    button_3100.enabled=True    
def onStopEditing(self, save_changes):
    button_3100.enabled=False

class LFM_3100(object):
    """Implementation for LFM_3100.button_3100 (Button)"""
    def __init__(self):
        self.enabled = False
        self.checked = False
    def onClick(self):
        ......

Це виглядає як рішення, яке варто спробувати. Дякую
користувач18412

4

Я публікую ще одну відповідь, тому що я вивчив новий метод перевірки стану редактора в ArcMap, використовуючи разом ArcObjects та Python. Моя відповідь значною мірою запозичує роботу, виконану Марком Седерхольмом, про яку йдеться у цій публікації: Як я можу отримати доступ до ArcObjects з Python? та приклади коду, які надав Метт Вілкі у своєму файлі "Snippits.py". Вам потрібно буде дотримуватися інструкцій, наведених у першій відповіді, щоб завантажити та встановити комтити, а потім отримати копію сценарію Snippets.py. Я публікую копію основних функцій із цього сценарію нижче.

Коли функція ArcMap_GetEditSessionStatus () викликається, вона перевірить поточний стан Редактора в ArcMap та поверне справжнє або хибне. Це дозволяє мені перевірити, чи готовий користувач користуватися моїм інструментом, чи потрібно їх запропонувати розпочати сеанс редагування. Недоліком цього методу є вимога встановити комтити до того, як ArcObjects можуть бути використані в Python, тому спільне використання інструменту, який вимагає цього пакета в середовищі офісу для багатьох користувачів, може бути неможливим. Маючи свій обмежений досвід, я не впевнений, як поєднати все це для легкого обміну як доповнення до інструменту Esri Python. Пропозиції, як це зробити, були б вдячні.

#From the Snippits.py file created by Matt Wilkie
def NewObj(MyClass, MyInterface):
    """Creates a new comtypes POINTER object where\n\
    MyClass is the class to be instantiated,\n\
    MyInterface is the interface to be assigned"""
    from comtypes.client import CreateObject
    try:
        ptr = CreateObject(MyClass, interface=MyInterface)
        return ptr
    except:
        return None

def CType(obj, interface):
    """Casts obj to interface and returns comtypes POINTER or None"""
    try:
        newobj = obj.QueryInterface(interface)
        return newobj
    except:
        return None

def CLSID(MyClass):
    """Return CLSID of MyClass as string"""
    return str(MyClass._reg_clsid_)

def GetApp(app="ArcMap"):
    """app must be 'ArcMap' (default) or 'ArcCatalog'\n\
    Execute GetDesktopModules() first"""
    if not (app == "ArcMap" or app == "ArcCatalog"):
        print "app must be 'ArcMap' or 'ArcCatalog'"
        return None
    import comtypes.gen.esriFramework as esriFramework
    import comtypes.gen.esriArcMapUI as esriArcMapUI
    import comtypes.gen.esriCatalogUI as esriCatalogUI
    pAppROT = NewObj(esriFramework.AppROT, esriFramework.IAppROT)
    iCount = pAppROT.Count
    if iCount == 0:
        return None
    for i in range(iCount):
        pApp = pAppROT.Item(i)
        if app == "ArcCatalog":
            if CType(pApp, esriCatalogUI.IGxApplication):
                return pApp
            continue
        if CType(pApp, esriArcMapUI.IMxApplication):
            return pApp
    return None


def GetModule(sModuleName):
    """Import ArcGIS module"""
    from comtypes.client import GetModule
    sLibPath = GetLibPath()
    GetModule(sLibPath + sModuleName)


def GetDesktopModules():
    """Import basic ArcGIS Desktop libraries"""
    GetModule("esriFramework.olb")
    GetModule("esriArcMapUI.olb")

#My added function for checking edit session status
def ArcMap_GetEditSessionStatus():

    GetDesktopModules()
    GetModule("esriEditor.olb")
    import comtypes.gen.esriSystem as esriSystem
    import comtypes.gen.esriEditor as esriEditor
    pApp = GetApp()
    pID = NewObj(esriSystem.UID, esriSystem.IUID)
    pID.Value = CLSID(esriEditor.Editor)
    pExt = pApp.FindExtensionByCLSID(pID)
    pEditor = CType(pExt, esriEditor.IEditor)
    if pEditor.EditState == esriEditor.esriStateEditing:
        print "Edit session active"
        return True
    else:
        print "Not in an edit session"
        return False

1
Це чудово працює. Я знаю, що це стара публікація, але якщо ви хочете упакувати це так, щоб воно було більш портативним, ви можете зробити модуль фрагментів як пакет python та включити до нього комтити. Я роблю це для своєї компанії, і я розмістив усі наші власні модулі Python на загальній мережі. Кожен раз, коли хтось встановлює / перевстановлює програмне забезпечення ArcGIS, у мене вони запускають пакетний файл, який модифікує їхній Desktop.pthфайл, щоб включати повний шлях до загальної мережі, тому кожен може автоматично імпортувати все.
crmackey

2

Як щодо використання модуля доступу до даних ? Схоже, ви можете розпочати сеанс редагування за допомогою цього модуля.

Кілька застережень:

  1. Я не пробував цей модуль і не впевнений, чи сумісний він 10.0. (Нове в 10.1?)
  2. У прикладі 1 показано використання withоператора. Це чудова парадигма, яку можна застосувати, оскільки вона добре обробляє потенційні винятки.
  3. Можливо, ви зможете перевірити, чи сеанс редагування вже активний, намагаючись запустити його в try / exceptоператорі.

Я фактично почав використовувати клас редактора в модулі доступу до даних, коли я розпочав цей проект, але його використання, здається, не мало значення. У тому числі "з arcpy.da.Editor (робоча область) як редагувати:" у моєму сценарії не активувався редактор, а спроба stopOperation / stop.Введення редактора не зупинило редактор. Але я можу зробити це неправильно ...
user18412

1

Ось так я вирішив свою проблему, не можу контролювати, чи користувався моїм інструментом хтось із сеансів редагування:

#Reference to mxd and layers script here. Then...
try:
    fields = ("OBJECTID")
    upCursor = arcpy.da.UpdateCursor(waterValves, fields)
    with upCursor as cursor:
        for row in cursor:
            pass
except:
    pythonaddins.MessageBox('You are not in an edit session', 'Warning', 0)

else:
#Rest of script

Сценарій працює, тому що він намагається створити UpdateCursor на шарі, який пізніше в сценарії має інший UpdateCursor. Це порушує поведінку модуля доступу до даних. Відповідно до сторінки ресурсів ESRI на сайті arcpy.da.UpdateCursor:

"Відкриття операцій одночасного вставлення та / або оновлення на одній робочій області за допомогою різних курсорів вимагає початку сеансу редагування."

Я не задоволений цим рішенням, тому що це скоріше хак, ніж те, що я собі уявляю, - це правильне скріптування скриптів. Кращі ідеї комусь?


1
Це лише ідея, але ви можете спробувати отримати доступ до об’єкта "Редактор" в ArcObjects і перевірити його властивість EditState, яка, здається, не вистачає в arcpy? Я ніколи не намагався маніпулювати ArcObjects з python, але ця тема розповідає про те, як це зробити?
Хорнбідд
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.