I'm trying to figure out what's wrong with my python syntax.
I have an attribute table with 4 fields containing paths to media files. I'm trying to convert the paths so that they behave more like hyperlinks on our network. The existing paths (added to the tables via 3rd party proprietary software) include network drive i.e. M:\GraniteXP\...
I'm trying to use find and replace to replace "M:\GraniteXP" with "\\vancouver.root.local\...\GraniteXP".
I can do this perfectly fine using field calculator in ArcMap as well as Model Builder. However, when I export the model to Python; the script runs (successfully), but the values are not updated. There is not error to tell me what's failing.
Here's a snippet from my script. I do have a MakeFeatureLayer prior to this snippet. (Note: this particular script is trying to change it back to the network drive pathing for testing purposes).
arcpy.SelectLayerByAttribute_management("lyrsdePipeInsp", "NEW_SELECTION", "Photo1 is not null")
arcpy.CalculateField_management("lyrsdePipeInsp", "Photo1", "Replace( [Photo1], \"\\\\vancouver.root.local\\cityapps\\GraniteXP\", \"M:\\GraniteXP\" )", "VB", "")
arcpy.SelectLayerByAttribute_management("lyrsdePipeInsp", "NEW_SELECTION", "Photo2 is not null")
arcpy.CalculateField_management("lyrsdePipeInsp", "Photo2", "Replace( [Photo2], \"\\\\vancouver.root.local\\cityapps\\GraniteXP\", \"M:\\GraniteXP\" )", "VB", "")
arcpy.SelectLayerByAttribute_management("lyrsdePipeInsp", "NEW_SELECTION", "Photo3 is not null")
arcpy.CalculateField_management("lyrsdePipeInsp", "Photo3", "Replace( [Photo3], \"\\\\vancouver.root.local\\cityapps\\GraniteXP\", \"M:\\GraniteXP\" )", "VB", "")
arcpy.SelectLayerByAttribute_management("lyrsdePipeInsp", "NEW_SELECTION", "Video is not null")
arcpy.CalculateField_management("lyrsdePipeInsp", "Video", "Replace( [Video], \"\\\\vancouver.root.local\\cityapps\\GraniteXP\", \"M:\\GraniteXP\" )", "VB", "")
Thanks!
Eugene Durshpek
Solved! Go to Solution.
You've got your find string and replacement string in the wrong order.
Try:
arcpy.CalculateField_management("lyrsdePipeInsp", "Photo1", r'Replace( [Photo1],"M:", "\\vancouver.root.local")',"VB")
Or:
arcpy.CalculateField_management("lyrsdePipeInsp", "Photo1", r"!Photo1!.replace('M:', r'\\vancouver.root.local')", "PYTHON_9.3")
a pain with the double slash replacement, you could try replacement with "/"
>>> a = "c:\\path\\subpath\\file.tiff" >>> b = a.replace("\\","/") >>> b 'c:/path/subpath/file.tiff'
Thanks Dan. I will combine your suggestion with Luke's suggestion (below) and will hopefully have best of both worlds.
Eugene D.
It is a lot faster and easier to code this type of processing with an update cursor.
something like this would work for the code example you gave:
import arcpy fc = #the path to your feature class with arcpy.da.UpdateCursor(fc,["Photo1","Photo2","Photo3","Video"]) as update: for row in update: if row[0] is not None: row[0] = row[0].replace("\\vancouver.root.local\\cityapps\\GraniteXP", "M:\\GraniteXP") if row[1] is not None: row[1] = row[1].replace("\\vancouver.root.local\\cityapps\\GraniteXP", "M:\\GraniteXP") if row[2] is not None: row[2] = row[2].replace("\\vancouver.root.local\\cityapps\\GraniteXP", "M:\\GraniteXP") if row[3] is not None: row[3] = row[3].replace("\\vancouver.root.local\\cityapps\\GraniteXP", "M:\\GraniteXP") update.updateRow(row)
Thank you Luke, I will give this a try. I'm a novice and wasn't sure how to apply the update cursor function to my scenario. I appreciate your quick response.
Eugene D.
I am testing this within a session of ArcMap and am getting Runtime Error: Insufficient permissions to edit the feature class [STATE_ID = 207215] which is odd because I can edit and save outside of python.
Are you working from an SDE geodatabase? In either case when I see this error I find that opening a da Editor helps:
import arcpy workspace = # path to you workspace fc = # the path to your feature class with arcpy.da.Editor(workspace) as edit: with arcpy.da.UpdateCursor(fc,["Photo1","Photo2","Photo3","Video"]) as update: for row in update: if row[0] is not None: row[0] = row[0].replace("\\vancouver.root.local\\cityapps\\GraniteXP", "M:\\GraniteXP") if row[1] is not None: row[1] = row[1].replace("\\vancouver.root.local\\cityapps\\GraniteXP", "M:\\GraniteXP") if row[2] is not None: row[2] = row[2].replace("\\vancouver.root.local\\cityapps\\GraniteXP", "M:\\GraniteXP") if row[3] is not None: row[3] = row[3].replace("\\vancouver.root.local\\cityapps\\GraniteXP", "M:\\GraniteXP") update.updateRow(row)
Thank you Luke;
Yes, I am editing an SDE feature class. I have updated my script (see below) but am now getting a "RuntimeError: cannot open workspace"; I will clean it up once I can get it to work.
import arcpy workspace = "M:/GIS/Support_Files/DataConnectionsADMIN/SewerVan_NT_SQLGIS1.sde/SewerVan.VANSEWER.SwrPipeInspected" fc = "SewerVan.VANSEWER.SwrPipeInspected" with arcpy.da.Editor(workspace) as edit: with arcpy.da.UpdateCursor(fc,["Photo1","Photo2","Photo3","Video"]) as update: for row in update: if row[0] is not None: row[0] = row[0].replace("//vancouver.root.local/cityapps/GraniteXP", "M:/GraniteXP") if row[1] is not None: row[1] = row[1].replace("//vancouver.root.local/cityapps/GraniteXP", "M:/GraniteXP") if row[2] is not None: row[2] = row[2].replace("//vancouver.root.local/cityapps/GraniteXP", "M:/GraniteXP") if row[3] is not None: row[3] = row[3].replace("//vancouver.root.local/cityapps/GraniteXP", "M:/GraniteXP") update.updateRow(row)
I'm not sure if there is an easy way to use the cursors in an ArcSDE geodatabase environment. You could look at this forum here that shows a work around. If you cannot get that figured out you may want to attempt Luke Pinner's suggestion below.
Not by chance a 64-bit? see below
Field calculations with a VB Expression type are not supported on 64-bit products, including ArcGIS Pro, ArcGIS for Desktop—Background Geoprocessing (64-bit) and ArcGIS for Server. To successfully use Calculate Field in these products, expressions should be converted to Python, or in the case of Background Geoprocessing (64-bit), background processing can alternatively be disabled.