I am trying to convert polygon geometry from one feature class to a 2 point line feature in another feature class. I am reading the data for the polygon(Anno) feature class with a Search Cursor and using an Insert cursor to add the update feature to the line feature class. The logic here basically work within ArcMap and ArcGIS Pro. But I want to run as a standalone script and it errors out when preforming the inscursor.insertRow(nrow). Not really sure what I am missing. The data is stored in an Enterprise database with the connection saved in the script's folder. Any help or suggests would be greatly appreciated.
import arcpy
import datetime
# Local variables:
web_esmtanno = "GISadmin to WebRandolph.sde\\WebRandolph.GISADMIN.esmtanno"
web_lotanno = "GISadmin to WebRandolph.sde\\WebRandolph.GISADMIN.lotanno"
web_LotAnnoLine = "GISadmin to WebRandolph.sde\\webrandolph.GISADMIN.TaxAnnotation\\webrandolph.GISADMIN.LotAnnoLine"
web_EsmtAnnoLine = "GISadmin to WebRandolph.sde\\webrandolph.GISADMIN.EsmtAnnoLine"
DB = "GISadmin to WebRandolph.sde"
arcpy.env.workspace = DB
def AnnotoLine(AnnoFS, LineFS):
try:
msg = arcpy.Describe(LineFS).baseName + " - " + arcpy.Describe(LineFS).dataType
print(msg)
msg = arcpy.Describe(AnnoFS).baseName + " - " + arcpy.Describe(AnnoFS).dataType
print (msg)
print (arcpy.Describe(AnnoFS).catalogPath)
inscursor = arcpy.da.InsertCursor(LineFS,['SHAPE@','TEXTSTRING','PID'])
cursor = arcpy.da.SearchCursor(AnnoFS,['OID@','SHAPE@','TextString'])
for row in cursor:
#print("In row cursor")
pntcnt = 0
ID = row[0]
poly = row[1]
txt = row[2].strip()
if poly.type == 'polygon':
poly1 = poly.getPart(0)
for pnt in poly1:
# print("Point: " + str(pntcnt))
if pntcnt == 0:
spoint = pnt
pntcnt += 1
# print(str(ID) + "(" + str(pntcnt) + ")-" + str(spoint.X) + "," + str(spoint.Y))
else:
if pntcnt < 4:
epoint = pnt
pntcnt += 1
# print (str(ID) + "(" + str(pntcnt) + ")-" + str(epoint.X) + "," + str(epoint.Y))
spref = poly.spatialReference
parray = arcpy.Array([spoint,epoint])
pline = arcpy.Polyline(parray,spref)
nrow = ([pline,text,ID])
inscursor.insertRow(nrow)
print (ID + ": was processed.")
else:
print (ID + ": shape invalid.")
except:
print("Error Inserting Rows" + arcpy.GetMessages(2))
finally:
del nrow, inscursor
del row, cursor
print ("Start time: " + datetime.datetime.now().strftime("%m/%d/%Y %I:%M%p"))
### Process: Update Parcel Annotation
try:
arcpy.DeleteFeatures_management(web_EsmtAnnoLine)
print "Cleared EsmtAnnoLine"
AnnotoLine(web_esmtanno,web_EsmtAnnoLine)
except:
##print "!! Could not update Annotation!!!"
msg = "Error updating Parcel Annotation!!!" + '\n'
msg += arcpy.GetMessages(2) + '\n'
print(msg)
##email_msg.sendmsg(msg,"Error UpdateWebAnno.py")
print "Finish time: " + datetime.datetime.now().strftime("%m/%d/%Y %I:%M%p")
Solved! Go to Solution.
I finally got this to work. A couple of typos and I moved the data out of a Geodataset which I think had locks.
import arcpy
import datetime
#import email_msg
# Local variables:
web_esmtanno = "GISadmin to WebRandolph.sde\\WebRandolph.GISADMIN.esmtanno"
web_lotanno = "GISadmin to WebRandolph.sde\\WebRandolph.GISADMIN.lotanno"
web_LotAnnoLine = "GISadmin to WebRandolph.sde\\webrandolph.GISADMIN.TaxAnnotation\\webrandolph.GISADMIN.LotAnnoLine"
web_EsmtAnnoLine = "GISadmin to WebRandolph.sde\\webrandolph.GISADMIN.EsmtAnnoLine"
DB = "GISadmin to WebRandolph.sde"
arcpy.env.workspace = DB
def AnnotoLine(AnnoFS, LineFS):
try:
msg = arcpy.Describe(LineFS).baseName + " - " + arcpy.Describe(LineFS).dataType
print(msg)
msg = arcpy.Describe(AnnoFS).baseName + " - " + arcpy.Describe(AnnoFS).dataType
print (msg)
print (arcpy.Describe(AnnoFS).catalogPath)
inscursor = arcpy.da.InsertCursor(LineFS,['SHAPE@','TEXTSTRING','PID'])
cursor = arcpy.da.SearchCursor(AnnoFS,['OID@','SHAPE@','TextString'])
for row in cursor:
print("In row cursor")
pntcnt = 0
ID = row[0]
poly = row[1]
txt = row[2].strip()
if poly.type == 'polygon':
poly1 = poly.getPart(0)
for pnt in poly1:
# print("Point: " + str(pntcnt))
if pntcnt == 0:
spoint = pnt
pntcnt += 1
# print(str(ID) + "(" + str(pntcnt) + ")-" + str(spoint.X) + "," + str(spoint.Y))
else:
if pntcnt < 4:
epoint = pnt
pntcnt += 1
# print (str(ID) + "(" + str(pntcnt) + ")-" + str(epoint.X) + "," + str(epoint.Y))
spref = poly.spatialReference
parray = arcpy.Array([spoint,epoint])
pline = arcpy.Polyline(parray,spref)
print("Polyline set")
nrow = ([pline,txt,ID])
inscursor.insertRow(nrow)
print (str(ID) + ": was processed.")
else:
print (str(ID) + ": shape invalid.")
except arcpy.ExecuteError:
print(arcpy.GetMessages())
finally:
del inscursor
del row, cursor
print ("Start time: " + datetime.datetime.now().strftime("%m/%d/%Y %I:%M%p"))
### Process: Update Parcel Annotation
try:
arcpy.DeleteFeatures_management(web_EsmtAnnoLine)
print "Cleared EsmtAnnoLine"
AnnotoLine(web_esmtanno,web_EsmtAnnoLine)
except arcpy.ExecuteError:
##print "!! Could not update Annotation!!!"
msg = "Error updating Parcel Annotation!!!" + '\n'
msg += arcpy.GetMessages()
print(msg)
##email_msg.sendmsg(msg,"Error UpdateWebAnno.py")
I'd suggest catching the exceptions (which also catches arcpy's exceptions) and see if there is anything else causing it to error.
except Exception as ex:
print("Error Inserting Rows" + ex))
Second thought is do you need to maybe start an edit session? Is the data versioned?
I finally got this to work. A couple of typos and I moved the data out of a Geodataset which I think had locks.
import arcpy
import datetime
#import email_msg
# Local variables:
web_esmtanno = "GISadmin to WebRandolph.sde\\WebRandolph.GISADMIN.esmtanno"
web_lotanno = "GISadmin to WebRandolph.sde\\WebRandolph.GISADMIN.lotanno"
web_LotAnnoLine = "GISadmin to WebRandolph.sde\\webrandolph.GISADMIN.TaxAnnotation\\webrandolph.GISADMIN.LotAnnoLine"
web_EsmtAnnoLine = "GISadmin to WebRandolph.sde\\webrandolph.GISADMIN.EsmtAnnoLine"
DB = "GISadmin to WebRandolph.sde"
arcpy.env.workspace = DB
def AnnotoLine(AnnoFS, LineFS):
try:
msg = arcpy.Describe(LineFS).baseName + " - " + arcpy.Describe(LineFS).dataType
print(msg)
msg = arcpy.Describe(AnnoFS).baseName + " - " + arcpy.Describe(AnnoFS).dataType
print (msg)
print (arcpy.Describe(AnnoFS).catalogPath)
inscursor = arcpy.da.InsertCursor(LineFS,['SHAPE@','TEXTSTRING','PID'])
cursor = arcpy.da.SearchCursor(AnnoFS,['OID@','SHAPE@','TextString'])
for row in cursor:
print("In row cursor")
pntcnt = 0
ID = row[0]
poly = row[1]
txt = row[2].strip()
if poly.type == 'polygon':
poly1 = poly.getPart(0)
for pnt in poly1:
# print("Point: " + str(pntcnt))
if pntcnt == 0:
spoint = pnt
pntcnt += 1
# print(str(ID) + "(" + str(pntcnt) + ")-" + str(spoint.X) + "," + str(spoint.Y))
else:
if pntcnt < 4:
epoint = pnt
pntcnt += 1
# print (str(ID) + "(" + str(pntcnt) + ")-" + str(epoint.X) + "," + str(epoint.Y))
spref = poly.spatialReference
parray = arcpy.Array([spoint,epoint])
pline = arcpy.Polyline(parray,spref)
print("Polyline set")
nrow = ([pline,txt,ID])
inscursor.insertRow(nrow)
print (str(ID) + ": was processed.")
else:
print (str(ID) + ": shape invalid.")
except arcpy.ExecuteError:
print(arcpy.GetMessages())
finally:
del inscursor
del row, cursor
print ("Start time: " + datetime.datetime.now().strftime("%m/%d/%Y %I:%M%p"))
### Process: Update Parcel Annotation
try:
arcpy.DeleteFeatures_management(web_EsmtAnnoLine)
print "Cleared EsmtAnnoLine"
AnnotoLine(web_esmtanno,web_EsmtAnnoLine)
except arcpy.ExecuteError:
##print "!! Could not update Annotation!!!"
msg = "Error updating Parcel Annotation!!!" + '\n'
msg += arcpy.GetMessages()
print(msg)
##email_msg.sendmsg(msg,"Error UpdateWebAnno.py")
Seeing the ArcPy errors helped.
Depending on your needs, you might want to wrap your geoprocessing functions within a Try/Except block. We have several scripts that we run in off hours so if something goes south, we like to get an email telling us so. The except block invokes the sendEmail() def. We also like to log all the processes so we can see what worked and what didn't:
def createAliasTable(msdCenterlines,centerlinesAlias,logoutput):
defName = 'Create Alias Table'
try:
select = "NAME >= 'A'"
arcpy.management.MakeFeatureLayer(msdCenterlines, 'centerlinesLyr', select)
arcpy.TruncateTable_management(centerlinesAlias)
arcpy.management.Append('centerlinesLyr',centerlinesAlias,'NO_TEST')
createTime = time.strftime('%Y-%m-%d %H:%M:%S')
logoutput.write(f'Success: completed {defName} at {createTime}\n')
except Exception as err:
failTime = time.strftime('%Y-%m-%d %H:%M:%S')
logoutput.write(f'Failure: Unable to complete {defName} at {failTime}\n ')
logoutput.write(f'{err}\n')
sendEmail(err)
Using the try/except approach, if the script tosses an error somewhere along the line, it won't totally blow up and shut down. We standardize all of our scripts with geoprocessing defs and call them from the main def, passing variables as arguments/parameters set there.
def main():
logFile = r"N:\GIS\Scripts\Logs\CreateCityWorksLocator.txt"
if os.path.exists(logFile):
os.remove(logFile)
logoutput = open(logFile,'a')
startUp(logoutput)
#set input parameters for various defs()
ws = r'N:\GIS\Geocoding\CityWorksLocators\GeocodingData.gdb'
sde = r'\\path\to\connectionFile\SLCOmsd@MSD.sde'
municipalities = f'{sde}\MSD.SLCOMSD.MunicipalitiesMSD'
centerlinesAlias = f'{ws}\CenterlinesMSD_Alias'
locatorDir = r'N:\GIS\Geocoding\CityWorksLocators\Locators\Joes'
parcels = r'J:\ConnectionFile\aDifferent.sde\MSD.SLCOMSD.SLCo_Parcels'
slcoCenterlines = f'{sde}\MSD.SLCOMSD.SLCo_Centerlines'
slcoAddressPoints = f'{sde}\MSD.SLCOMSD.SLCo_AddressPoints'
msdCenterlines = f'{sde}\MSD.SLCOMSD.CenterlinesMSD'
msdAddressPoints = f'{sde}\MSD.SLCOMSD.SiteAddressPointsMSD'
msdFgbAddressPoints = f'{ws}\SiteAddressPointsMSD'
#call the defs comment out as needed for testing purposes
#arcelsToFGDB(parcels,ws,municipalities,logoutput)
#createParcelLocator(parcels,locatorDir,logoutput)
#createNonMsdParcelLocator(ws,locatorDir,logoutput)
#createAliasTable(msdCenterlines,centerlinesAlias,logoutput)
#nonMsdAddressPoints(ws,slcoAddressPoints,municipalities,logoutput)
#nonMsdCenterlines(ws,slcoCenterlines,municipalities,logoutput)
#nonMsdLocator(ws,locatorDir,logoutput)
#createMsdAddressPoints(ws,msdAddressPoints,logoutput)
#msdLocator(ws,centerlinesAlias,msdFgbAddressPoints,msdCenterlines,locatorDir,logoutput)
compositeLocator(locatorDir,logoutput)
if __name__ == '__main__':
main()
Notice that all the calls to the various defs are commented out; with a modular approach, you can only run the defs you want to.