ArcMap'ın düzenleme oturumunda olup olmadığını ArcPy ile kontrol etmek istiyor musunuz?


11

Bir özellik sınıfı özniteliğini diğerine kopyalayarak iş arkadaşlarımın iş akışını hızlandırmaya yardımcı olan bir Python eklenti düğmesi oluşturdum. Hedef özellik sınıfındaki bir satırı güncellemek için arcpy.UpdateCursor işlevini kullanır. Şimdi olduğu gibi, bu düğme komut dosyası düzenleme modundan bağımsız olarak çalıştırılabilir. Açıkçası bir düzenleme oturumunda çalıştırıldığında, kullanıcı düzenlemeyi durdurmayı ve değişiklikleri kaydetmeyi seçemez, ancak komut dosyası bir düzenleme oturumunun dışında çalıştığında durum böyle değildir.

ArcMap şu anda bir düzenleme oturumunda değilse, komut dosyasına çalışmasını durduracak komut dosyasına nasıl bir denetim ekleyebilirim?

Bu ArcMap 10 ve 10.1 ile ilgilidir


Ayrıca, bir düzenleme oturumunda bulunmadan tablolardaki güncellemelere normalde izin verilmediğini doğrulamak için diğer ArcMap kullanıcılarıyla da kontrol etmek istiyorum.

Peki bu komut dosyası bir düzenleme oturumu dışında nasıl çalışıyor?

Bu komut dosyası ayrıca ArcMap'ın gerçekleştirdiği görünüşte tesadüfi seçim sırası hakkında başka bir soru getiriyor, bu sadece 2. özellik sınıfı tablosunu bir listeden güncellediğimde benim için çalışıyor, ancak bu başka bir gün için.

İşte şu anda çalıştığı gibi komut dosyası (10.1 editör uygulaması olmadan):

Kullanıcının düzenleme oturumunda olduğundan emin olmak için bir kontrol nasıl eklenir?

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

Veri erişim modülü düzenleyicisi, standart Düzenleyiciden bağımsız olarak çalışıyor gibi görünüyor. Etkin bir düzenleme oturumu testi hakkında ek fikirleri memnuniyetle karşılarım. -Karl
KarlJr

Biraz daha bilgi verebilir misiniz? Modülü keşfetmeyenlerimiz için sizi bu sonuca götüren nedir?
Jay Laura

Yanıtlar:


6

İşte bu yazıyı temel alan genel bir işlev.

Belki de bu ArcObjects çözümünden biraz daha kludgy, ama elbette çok daha az güçlük gibi görünüyor! Basit, karmaşık olmaktan iyidir. Olmadığı zamanlar hariç.

Örnek kullanım:

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

kod:

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 Nice konsept, ancak OP bir düzenleme oturumunda değilse durdurmak ve bir düzenleme oturumunda ise devam etmek istiyor . Cevabınız tam tersini yapıyor. Muhtemelen bunu tersine çevirmek için fazla zaman almazdı.
Midavalo

OP sorununu zaten çözdü, bu yazı daha genel olarak kullanışlı bir fonksiyonla buzlanıyor. Örneğimi işlevin nasıl kullanıldığı konusunda daha net olacak şekilde değiştirdim.
Curtis Price

4

Bu soruna benim çözüm Arcpy Addin Araç Çubuğu için kullanılabilir uzantıları kullanmak oldu. Bir düzenleme oturumunun başlamasını veya bitmesini dinleyen bir uzantı ekledim. Tüm düğmeleri benim çubuğum var: self.enable = False "ile başlamak ve sonra bu düğmeler sonra bir düzenleme oturumu başlatarak veya durdurarak etkinleştirmek veya devre dışı bırakılır.

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):
        ......

Bu, denemeye değer bir çözüm gibi görünüyor. Teşekkür ederim
user18412

4

ArcObjects ve Python'u birlikte kullanarak ArcMap'ta Editör durumunu kontrol etmek için yeni bir yöntem öğrendiğim için başka bir cevap gönderiyorum. Cevabım bu yazıda atıfta bulunulan Mark Cederholm tarafından yapılan çalışmadan büyük ölçüde ödünç alıyor: Python'dan ArcObjects'e nasıl erişebilirim? ve Matt Wilkie tarafından "Snippits.py" dosyasında sağlanan kod örnekleri. Comtypes'i indirip yüklemek ve ardından Snippets.py betiğinin bir kopyasını almak için ilk cevapta verilen talimatları izlemeniz gerekir. Aşağıdaki komut dosyasından temel işlevlerin bir kopyasını gönderiyorum.

ArcMap_GetEditSessionStatus () işlevi çağrıldığında, ArcMap'ta Editör'ün geçerli durumunu kontrol eder ve true veya false değerini döndürür. Bu, bir kullanıcının aracımı kullanmaya hazır olup olmadığını veya bir düzenleme oturumu başlatmaları istenip istenmediğini kontrol etmemi sağlar. Bu yöntemin dezavantajı, ArcObjects'in Python'da kullanılabilmesi için önce comtypes kurulması gerekliliğidir, bu nedenle bu paketi gerektiren bir aracın çok kullanıcılı bir ofis ortamında paylaşılması mümkün olmayabilir. Sınırlı deneyimimle, Esri Python aracı eklentisi olarak kolay paylaşım için hepsini nasıl bir araya getireceğimi bilmiyorum. Bunun nasıl yapılacağına dair öneriler takdir edilecektir.

#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
Harika çalışıyor. Bunun eski bir yazı olduğunu biliyorum, ancak daha taşınabilir olması için paketlemek istiyorsanız, snippet modülünü bir python paketi olarak yapabilir ve içine comtypes ekleyebilirsiniz. Bunu şirketim için yapıyorum ve tüm özel Python modüllerini bir ağ paylaşımına yerleştirdim. Birisi ArcGIS yazılımını her yüklediğinde / yeniden yüklediğinde, Desktop.pthherkesin her şeyi otomatik olarak içe aktarabilmesi için dosyalarını ağ paylaşımının tam yolunu içerecek şekilde değiştiren bir toplu iş dosyası çalıştırmasını sağlarım .
crmackey

2

Veri erişim modülünü kullanmaya ne dersiniz ? Bu modülle bir düzenleme oturumu başlatabileceğiniz anlaşılıyor.

Birkaç uyarı:

  1. Bu modülü denemedim ve 10.0 uyumlu olup olmadığından emin değilim. (10.1 sürümünde yeni misiniz?)
  2. Örnek 1 bir withifadenin kullanımını göstermektedir . Bu, potansiyel istisnaları iyi ele aldığı için uygulanması büyük bir paradigmadır.
  3. Bir try / exceptifadede bir oturum başlatmayı deneyerek bir düzenleme oturumunun zaten canlı olup olmadığını test edebilirsiniz .

Aslında bu projeye başladığımda veri erişim modülünde Editor sınıfını kullanmaya başladım ama bunu kullanmak önemli değildi. Komut dosyasına "arcpy.da.Editor (çalışma alanı) ile düzenleme:" dahil etmek düzenleyiciyi etkinleştirmedi ve stopOperation / stop.Editing'i denemek editörü durdurmadı. Ama yanlış yapıyor olabilirim ...
user18412 23:13

1

Bu yüzden, aracımı kullanan birinin düzenleme oturumunda olup olmadığını kontrol edememe sorunumu şu şekilde düzelttim:

#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

Komut dosyası, komut dosyasında daha sonra başka bir UpdateCursor olan bir katman üzerinde bir UpdateCursor oluşturmaya çalıştığı için çalışır. Bu, veri erişim modülünün davranışını ihlal eder. Arcpy.da.UpdateCursor'daki ESRI Kaynakları sayfasına göre:

"Farklı imleçler kullanarak aynı çalışma alanında aynı anda ekleme ve / veya güncelleme işlemlerini açmak için bir düzenleme oturumu başlatılması gerekir."

Bu çözümden memnun değilim, çünkü uygun arcpy komut dosyası olduğunu düşündüğümden çok bir hack. Daha iyi fikirler var mı?


1
Bu sadece bir fikir ama ArcObjects Editör nesnesine erişmeyi ve arcpy eksik olan gibi görünen EditState özelliğini kontrol edebilirsiniz? Asla python ArcObjects manipüle etmeye çalıştım ama bu iş parçacığı nasıl yapılacağı hakkında konuşuyor?
Hornbydd
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.