Python add in- update two fields in one feature based on same fields of another

8061
43
Jump to solution
04-14-2014 11:10 AM
AndrewMosley
Emerging Contributor
I'm totally new to making add ins and quite novice at python itself but I have a script that executes perfectly as a script tool or simply in the python window of ArcMap. I want to make this a quick button click so I looked into making an add-in toolbar with a button.

Just to get the hang of making the addin i made a print "Hello World!" that works as expected.

However, it seems something is going wrong with my code when put into the add-in. I can only assume I'm missing some syntax due to my inexperience with python.

The situation here is I have a percels layer and an address points layer, which both contain a PIN and TMS number. I simply want to have the function select the address points within the parcel geometry, find the value of PIN and TMS from the parcel layer's attribute table, and update the same fields in the address points' attribute table. Again, the script I've written executes perfectly inside the python console in ArcMap but not as an add-in. Thanks for any hints you all might have!

So here's what I've got:

import arcpy import pythonaddins  class BlueBird(object):     """Implementation for BlueBird.button (Button)"""     def __init__(self):         self.enabled = True         self.checked = False     def onClick(self): arcpy.SelectLayerByLocation_management("Address Points","COMPLETELY_WITHIN","Parcels")  #insert if statement checking that only one parcel is selected to prevent selecting all address points  with arcpy.da.SearchCursor("Parcels",'PIN') as cursor:  for row in cursor:   storedPIN = row[0] with arcpy.da.UpdateCursor("Address Points",'PIN') as cursor:  for row in cursor:   row[0] = storedPIN   cursor.updateRow(row)  del cursor  with arcpy.da.SearchCursor("Parcels",'TMS') as cursor:  for row in cursor:   storedTMS = row[0] with arcpy.da.UpdateCursor("Address Points",'TMS') as cursor:  for row in cursor:   row[0] = storedTMS   cursor.updateRow(row)  del cursor, storedPIN, storedTMS
Tags (2)
0 Kudos
43 Replies
AndrewMosley
Emerging Contributor
So using that code I run into 2 errors:

The first error is due to unexpected indentations between the edit.start and edit.stop commands.
Upon some inspection of the arcpy.editor class help doc, it seems you have the option of either not indenting these or passing the editor using with:

with arcpy.da.Editor(workspace) as edit:

and there is then no need for the start and stop commands as this is automatically handled.

So I removed the indentation and ran into my second error:
Line 29:
edit = arcpy.da.Editor(workspace)
RuntimeError: cannot open workspace

So I passed a few of the beginning lines to pursue what I thought might be the suspicious bit of code:

import arcpy
import os
addressPoints = "Address Points"
mxd = arcpy.mapping.MapDocument('current')
df = arcpy.mapping.ListDataFrames(mxd)[0]
lyr = arcpy.mapping.ListLayers(mxd, addressPoints, df)[0]
print lyr
print lyr.workspacePath


print lyr returns Address Points as expected.
print lyr.workspacePath returns nothing.

We are then feeding the next line:

edit = arcpy.da.Editor(workspace)

an empty argument.

Meaning that the "Address Points" layer SEEMS to have an attribute named workspacePath but it is blank...unless I'm misinterpreting this?

Any thoughts?
0 Kudos
RichardFairhurst
MVP Alum
So using that code I run into 2 errors:

The first error is due to unexpected indentations between the edit.start and edit.stop commands.
Upon some inspection of the arcpy.editor class help doc, it seems you have the option of either not indenting these or passing the editor using with:

with arcpy.da.Editor(workspace) as edit:

and there is then no need for the start and stop commands as this is automatically handled.

So I removed the indentation and ran into my second error:
Line 29:
edit = arcpy.da.Editor(workspace)
RuntimeError: cannot open workspace

So I passed a few of the beginning lines to pursue what I thought might be the suspicious bit of code:

import arcpy
import os
addressPoints = "Address Points"
mxd = arcpy.mapping.MapDocument('current')
df = arcpy.mapping.ListDataFrames(mxd)[0]
lyr = arcpy.mapping.ListLayers(mxd, addressPoints, df)[0]
print lyr
print lyr.workspacePath


print lyr returns Address Points as expected.
print lyr.workspacePath returns nothing.

We are then feeding the next line:

edit = arcpy.da.Editor(workspace)

an empty argument.

Meaning that the "Address Points" layer SEEMS to have an attribute named workspacePath but it is blank...unless I'm misinterpreting this?

Any thoughts?


To get it done I would look at the layer properties and find out the workspace path and type in the string as a hard coded value.  The code I gave was from the help, but they said not all layer sources support it.  However, they did not spell out the alternatives for getting a path that the Editor will use to start up using code.  Anyway for now a hard coded punt should at least get the code functioning.

You may have to point to an .sde connection file, but I am not sure.  If you use a connection file than every user needs a duplicate of that connection file name on their machine.  Search the forum on SDE editing in Python, since it is a special situation that I am sure has come up before.
0 Kudos
AndrewMosley
Emerging Contributor
I haven't been able to find any information on pointing the workspace at a particular version of sde data unfortunately.

I did try simply hard coding the path of the sde and it threw an editing permission restricted error. Now that my brain has had a minute to sit still, that's quite a duh kind of error.

I'll see if the filepath is different for the actual layer when I get back into work and give that a go.

Which help article were you pulling from? I seemed to have missed it in my hours of pouring through esri resources.
0 Kudos
RichardFairhurst
MVP Alum
I haven't been able to find any information on pointing the workspace at a particular version of sde data unfortunately.

I did try simply hard coding the path of the sde and it threw an editing permission restricted error. Now that my brain has had a minute to sit still, that's quite a duh kind of error.

I'll see if the filepath is different for the actual layer when I get back into work and give that a go.

Which help article were you pulling from? I seemed to have missed it in my hours of pouring through esri resources.


My code was borrowed from example 2 in this help document.  I just assumed the indent was needed between start and stop operations since python almost always requires it, but I see that the example did not use indentations.

You could try this code, but you may have to cast the layer to its underlying feature class first:

import os
workspace = os.path.dirname(addressLeyer)
0 Kudos
AndrewMosley
Emerging Contributor
So I tried hardcoding the path name like so:

workspace = "C:\Users\mosleya\AppData\Roaming\ESRI\Desktop10.1\ArcCatalog\Connection to gisprod.sde"
edit = arcpy.da.Editor(workspace)

From this I get an error that says edits to this may only be made by the owner of the Default.sde DB (admin).

So I passed:
arcpy.da.ListVersions("C:\Users\mosleya\AppData\Roaming\ESRI\Desktop10.1\ArcCatalog\Connection to gisprod.sde")

and come up with a list of 20 expected version objects, [0] being default (I have to assume).

So I tried this for [0]-[19] in hopes of finding the direct workspace of my user name (which I have editing rights to):
version = arcpy.da.ListVersions("C:\Users\mosleya\AppData\Roaming\ESRI\Desktop10.1\ArcCatalog\Connection to gisprod.sde")[0]
workspace = (version)
edit = arcpy.da.Editor(workspace)

I get a "cannot open workspace" error for every single one. I know one of these must be my own version so I'm not sure if I have missed some crucial arcpy.da.Editor line or what. The only thought I have is that perhaps my version has a lock on it by default that must be unlocked to enable to editor and then relocked after the edit is done?
0 Kudos
JamesCrandall
MVP Alum
Just a quick shot in the dark, maybe try hard-coding the versioned .sde file instead of:

workspace = (version)


Just hard-code the workspace:

workspace = (r"C:\Users\mosleya\AppData\Roaming\ESRI\Desktop10.1\ArcCatalog\name of the versioned data connection.sde")
0 Kudos
AndrewMosley
Emerging Contributor
Looking in the folder at:
C:\Users\mosleya\AppData\Roaming\ESRI\Desktop10.1\ArcCatalog
I see a Connection to gisprod.sde file.

This is the same file for every user with a version, meaning its owner is administrator.

So hard-cording:
workspace = (r"C:\Users\mosleya\AppData\Roaming\ESRI\Desktop10.1\ArcCatalog\Connection to gisprod.sde")

produces the same error:
RuntimeError: Operation only allowed by the owner of the version [sde.DEFAULT]

My end game here is to start an edit session on a specific version under the DEFAULT.sde
Something like:
workspace = (r"C:\Users\mosleya\AppData\Roaming\ESRI\Desktop10.1\ArcCatalog\Connection to gisprod\VersionMOSLEYA.sde")

...if such a file path existed of course.
0 Kudos
RichardFairhurst
MVP Alum
Looking in the folder at:
C:\Users\mosleya\AppData\Roaming\ESRI\Desktop10.1\ArcCatalog
I see a Connection to gisprod.sde file.

This is the same file for every user with a version, meaning its owner is administrator.

So hard-cording:
workspace = (r"C:\Users\mosleya\AppData\Roaming\ESRI\Desktop10.1\ArcCatalog\Connection to gisprod.sde")

produces the same error:
RuntimeError: Operation only allowed by the owner of the version [sde.DEFAULT]

My end game here is to start an edit session on a specific version under the DEFAULT.sde
Something like:
workspace = (r"C:\Users\mosleya\AppData\Roaming\ESRI\Desktop10.1\ArcCatalog\Connection to gisprod\VersionMOSLEYA.sde")

...if such a file path existed of course.


You can change the version in the connection file to directly use the correct version for each user rather than leaving the connection set to use the default version. Access the Geodatabase Connection Properties and make the change and save it.  You do not need to change the connection name or have special admiinistrator rights to do this.  All users should use the same connection name and path to make the script set up the easiest, or else you need to detect the os username and follow a standardized connection naming convention based on that in your code.
0 Kudos
RichardFairhurst
MVP Alum
Also look at the ChangeVersion help.  It suggests that only after changing the version of a layer or table view from a direct sde connection should you start an edit session.  Shouldn't be the only approach, but we just need to get something to work.
0 Kudos
AndrewMosley
Emerging Contributor
That was it.

My connection just needed to be changed to default to the user.
Unfortunately the path still has to be hard-coded but that's still not a difficult setup process.

Thank you tons for your help! Mega thumbs up!
0 Kudos