ฉันต้องการสคริปต์บางสิ่งที่ไม่ได้เปิดเผยผ่านarcgisscripting
หรือ ArcPy
ฉันจะเข้าถึงArcObjectsจาก Python ได้อย่างไร
ฉันต้องการสคริปต์บางสิ่งที่ไม่ได้เปิดเผยผ่านarcgisscripting
หรือ ArcPy
ฉันจะเข้าถึงArcObjectsจาก Python ได้อย่างไร
คำตอบ:
ดาวน์โหลดและติดตั้งcomtypes * ใส่Snippets
โมดูลจาก Mark Cederholm ใน PYTHONPATH และคุณพร้อมแล้ว
from snippets102 import GetLibPath, InitStandalone
from comtypes.client import GetModule, CreateObject
m = GetModule(GetLibPath() + "esriGeometry.olb")
InitStandalone()
p = CreateObject(m.Point, interface=m.IPoint)
p.PutCoords(2,3)
print p.X, p.Y
สำหรับพื้นหลังเห็นมาร์ค Cederholm ของการนำเสนอสำหรับ UberPyGeeks ใน"การใช้ ArcObjects ในงูใหญ่" มีมุมมองแยกต่างหากสำหรับมุมมองนักพัฒนา VBA และ C ++ พวกเขาใช้Visual Studio (ใช่Expressคือ ok) และWindows SDKแต่ไม่จำเป็นต้องใช้เพียงแค่ ArcGIS, Python และ comtypes ก็เพียงพอแล้ว
* หมายเหตุสำหรับ 10.1+คุณต้องทำการเปลี่ยนแปลงเล็กน้อยautomation.py
ในโมดูล comtypes ดูArcObjects + comtypes ที่ 10.1
... หรือ: สมองหมดสติหรือเปล่า มองไปที่คตัวอย่าง # รหัสทำให้ดวงตาของคุณว่ายน้ำและพยายามที่คุณอาจคุณก็ไม่สามารถคิดเช่นเครน ? ดูนี่:
ใช่งานนำเสนอของ Mark Cederholm ที่ Matt Wilkie กล่าวไว้ข้างต้นเป็นจุดเริ่มต้นที่ดี สูตร / รหัสที่ Matt นำเสนอนั้นเป็นวิธีที่ลื่นไหลและอาจเป็นวิธีที่ดีที่สุดในการทำสิ่งต่างๆ ฉันต้องการพูดถึง แต่วิธีการบังคับกำลังดุร้ายที่ฉันใช้ใน ArcGIS 10.0 ฉันมีสคริปต์อัตโนมัติหลายตัว (แบบสแตนด์อโลนนอกขอบเขตแอปพลิเคชัน) ที่ฉันใช้วิธีนี้และพวกมันก็ใช้ได้ดี ถ้าความเร็วสูงสุดเป็นสิ่งที่น่ากังวลคุณอาจต้องใช้วิธีแก้ปัญหาของ Matt และทำตามนั้น
ฉันใช้แพ็คเกจ comtypes เพื่อบังคับให้ห่อของ ArcObjects libraries (.olb) ทั้งหมด จากนั้น Python ก็สามารถเข้าถึง ArcObjects ทั้งหมดได้ ผมได้รับรหัสการตัดจากแฟรงก์ Perks ผ่านโพสต์ฟอรั่ม ESRI ฉันมีรหัสของตัวเองที่ทำสิ่งเดียวกันโดยหลักแล้ว แต่มันบวมและใช้งานได้ดีในขณะที่เขาสวยกว่ามาก ดังนั้น:
import sys, os
if '[path to your Python script/module directory]' not in sys.path:
sys.path.append('[path to your Python script/module directory]')
import comtypes
#force wrapping of all ArcObjects libraries (OLBs)
import comtypes.client
# change com_dir to whatever it is for you
com_dir = r'C:\Program Files (x86)\ArcGIS\Desktop10.0\com'
coms = [os.path.join(com_dir, x) for x in os.listdir(com_dir) if os.path.splitext(x)[1].upper() == '.OLB']
map(comtypes.client.GetModule, coms)
จากนั้นค่อนข้างตรงไปตรงมาจากการนำเสนอของ Mark Cederholm:
import comtypes.gen.esriFramework
pApp = GetApp()
def GetApp():
"""Get a hook into the current session of ArcMap"""
pAppROT = NewObj(esriFramework.AppROT, esriFramework.IAppROT)
iCount = pAppROT.Count
if iCount == 0:
print 'No ArcGIS application currently running. Terminating ...'
return None
for i in range(iCount):
pApp = pAppROT.Item(i) #returns IApplication on AppRef
if pApp.Name == 'ArcMap':
return pApp
print 'No ArcMap session is running at this time.'
return None
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
แค่นั้นแหละ. คุณควรมีสิทธิ์เข้าถึง ArcObjects อย่างเต็มรูปแบบเริ่มต้นด้วยวัตถุ pApp ที่เป็น IApplication บนวัตถุ AppRef จากประสบการณ์ของผมการห่อของ ArcObjects ไลบรารี่ในการรันครั้งแรกนั้นไม่ช้าอย่างไม่น่าเชื่อ ห้องสมุดได้รับการรวบรวมและเรียบเรียงแล้วดังนั้นสิ่งต่าง ๆ จึงเร็วกว่ามาก
ที่เพิ่มเข้ามา: มีข้อควรระวังขนาดใหญ่ที่มาพร้อมกับสิ่งนี้ ฟังก์ชัน NewObj ที่กำหนดในที่นี้สมมติว่าสคริปต์ Python กำลังถูกเรียกใช้อยู่ระหว่างดำเนินการ ถ้าไม่ฟังก์ชั่นนี้จะสร้างวัตถุในกระบวนการ Python (เช่นออกนอกกระบวนการ) และการอ้างอิงวัตถุจะผิด เพื่อสร้างวัตถุในกระบวนการจากสคริปต์ Python ภายนอกคุณควรใช้ IObjectFactory ดูความคิดเห็นและเคล็ดลับของ Kirk Kuykendall ในโพสต์แลกเปลี่ยนนี้สำหรับข้อมูลเพิ่มเติม
ฉันจะเข้าถึง arcobjects จาก python ได้อย่างไร
หากสิ่งที่คุณกำลังมองหาคือฟังก์ชั่นเฉพาะที่มีอยู่และอยู่ในรหัส C ++ Arcobjects ทางออกที่ดีที่สุดของคุณคือการสร้างวิธีการ C ++ เพื่อโทรหาพวกเขา .... แล้วสร้างไพเพอร์แรปเปอร์
มีหลายวิธีในการเข้าถึงวิธี C ++ จาก python และผู้คนมากมายที่ใช้เครื่องมือเช่นSWIGเพื่อสร้างคลาส python โดยอัตโนมัติจากลายเซ็นเมธอด C ++ เป็นประสบการณ์ของฉันที่ API ที่สร้างอัตโนมัติเหล่านี้ได้รับสิ่งที่น่ารังเกียจเมื่อผ่านประเภท C ++ ที่ไม่ใช่เจ้าของภาษา (int, float) และไม่เคย ' ไพเราะ ' มากนัก
โซลูชันที่แนะนำของฉันคือใช้ ctypes API บทแนะนำที่ยอดเยี่ยมอยู่ที่นี่: http://python.net/crew/theller/ctypes/tutorial.html
ขั้นตอนพื้นฐานคือ:
นี่อาจเป็นวิธีทั่วไปในการอ้างอิงรหัส C / C ++ จากภายในไพ ธ อนมันอาจจะง่ายกว่ามากในระยะยาวหากคุณไม่ต้องจัดการกับวัตถุ COM นอกจากนี้ยังจะช่วยให้การทำงานเฉพาะของระบบทั้งหมดอยู่ในการรวบรวมวัตถุห้องสมุดที่เชื่อมโยง (ดังนั้นงูหลามจะไม่ใช้งานเฉพาะระบบ / งูหลาม)
อีกทางเลือกหนึ่งคือใช้Python สำหรับ. NET - ซึ่งง่ายต่อการติดตั้งและสามารถทำงานกับ. NET DLLs ใด ๆ รวมถึง ArcObjects
ฉันไม่เคยประสบปัญหาเกี่ยวกับการตรวจจับระหว่างดำเนินการและเปิดอินสแตนซ์ของ ArcMap และการเพิ่มและจัดการเลเยอร์ทำงานได้ดีสำหรับฉัน
ข้อกำหนดเพียงอย่างเดียวคือโฟลเดอร์ที่มีไลบรารี Python สำหรับ. NET และติดตั้ง Python มาตรฐาน
รายละเอียดเพิ่มเติมและสคริปต์ตัวอย่างที่นี่ สคริปต์ตัวอย่างสามารถดูได้โดยตรงที่http://gist.github.com/923954
น่าเสียดายที่ในขณะนี้สามารถใช้งานได้โดยไม่มีปัญหากับเครื่องพัฒนาท้องถิ่นการปรับใช้ที่อื่นจำเป็นต้องใช้ ArcObjects SDK และ Visual Studio (รวมถึงรุ่น Express ฟรี) ดูที่การปรับใช้ ArcObject .NET DLLs
วิธีการหนึ่งที่ฉันไม่เห็นในคำตอบอื่น ๆ คือใช้วิธีเดียวกันกับที่ห้องสมุด arcpy ใช้ เช่นใน C: \ Program Files \ ArcGIS \ Desktop10.0 \ arcpy \ arcpy \ cartography.py, เราเห็น Python เรียกเครื่องมือ ArcObjects โดยใช้ fixargs และฟังก์ชั่นการแปลงวัตถุ
ฉันไม่ได้ตกลงที่จะโพสต์เกี่ยวกับที่นี่เนื่องจากโค้ดระบุว่า "ความลับทางการค้า: ESRI PROPRIETARY และความลับ"; แต่คุณจะพบมันที่อื่นบนเว็บด้วย อย่างไรก็ตามนี่ดูเหมือนจะเป็นวิธีที่ง่ายในการเรียกใช้ฟังก์ชั่นเช่นSimplifyBuilding_cartography()
โดยไม่ต้องติดตั้ง comtypes หรือไลบรารีเพิ่มเติมอื่น ๆ
แก้ไข:
ดูความคิดเห็นของ Jason ด้านล่าง เสียงเหมือนทำข้างต้นจะไม่ซื้อคุณมาก