How to reference AGOL Hosted Feature Layers in arcpy.metadata module?

727
4
Jump to solution
03-06-2023 04:54 PM
Labels (3)
TorrinHultgren2
New Contributor III

We'd really like to build some automation into our management of ArcGIS Online Hosted Feature Service Metadata, but can't figure out the syntax for referring to these services using the arcpy.metadata.Metadata() module. The documentation suggests that a URI is sufficient, but apparently a URL doesn't qualify:

desc = arcpy.Describe("https://services.arcgis.com/cJ9YHowT8TU7DUyn/ArcGIS/rest/services/FAC_Superfund_Site_Boundaries_EPA_Public/FeatureServer/0")
print(desc.name)
L0Superfund_Site_Boundaries
print(desc.dataType)
FeatureClass
print(desc.dataElementType)
DEFeatureClass
target_metadata = arcpy.metadata.Metadata("https://services.arcgis.com/cJ9YHowT8TU7DUyn/ArcGIS/rest/services/FAC_Superfund_Site_Boundaries_EPA_Public/FeatureServer/0")
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "C:\Users\thultgre\AppData\Local\Programs\ArcGIS\Pro\Resources\ArcPy\arcpy\metadata.py", line 102, in __init__
    self._arc_object = arcgisscripting.metadata.Metadata(uri)
RuntimeError

We can edit the metadata for these hosted feature services in ArcGIS Pro and use the import/export tools on the toolbar, but we'd really like to use python to manipulate these records as well. What are we missing? Hopefully it's something straightforward. 

 

1 Solution

Accepted Solutions
TorrinHultgren2
New Contributor III

Spent a while going back and forth on this with Esri Support, and ended up with several workarounds and an enhancement request.  The key takeaway is that today the arcpy.metadata module does not support hosted feature services, and the enhancement request is to address that.

Workarounds include:

Rolling your own with python "requests". This is pretty straightforward... until you want to edit non-public metadata records owned by enterprise accounts.  

import requests
# Example URL for top-level feature service
url = "https://services.arcgis.com/cJ9YHowT8TU7DUyn/arcgis/rest/services/FRS_INTERESTS/FeatureServer/info/metadata"
# Example URL for feature service layer
url = "https://services.arcgis.com/cJ9YHowT8TU7DUyn/ArcGIS/rest/services/FRS_INTERESTS/FeatureServer/0/metadata"

# Send an HTTP GET request to fetch the metadata XML
response = requests.get(metadata_url)

if response.status_code == 200:
    metadata_xml = response.text
    print(metadata_xml)
else:
    print(f"Error fetching metadata: {response.status_code}")

This code returns the raw ArcGIS Metadata, which is important. If you add format parameters (?format=default&f=xml) to the URLs above, it will run the XML through a stylesheet and while the result might then be standards-compliant, it won't be your original metadata, and may not be recognized by ArcGIS Pro.

Using the ArcGIS API for Python. This helps with access to non-public content, but doesn't appear to allow the source ArcGIS metadata to be returned for feature service layers, only the top level service metadata. 

# Example of retrieving Feature Service metadata:
from arcgis.gis import GIS
import arcgis
from arcgis.features import FeatureLayerCollection
from arcpy import metadata as md
import arcpy
gis = GIS('home')
test = "https://services.arcgis.com/cJ9YHowT8TU7DUyn/ArcGIS/rest/services/FRS_INTERESTS/FeatureServer" 
flc = FeatureLayerCollection(test, gis)
flcitem = arcgis.gis.Item(gis,flc.properties["serviceItemId"])
target_md = md.Metadata(flcitem.metadata)
print(target_md.xml)

# Example of retrieving Feature Service Layer metadata 
from arcgis.gis import GIS
from arcgis.features import FeatureLayer
from arcpy import metadata as md
gis = GIS('home')
t = "https://services.arcgis.com/cJ9YHowT8TU7DUyn/ArcGIS/rest/services/FRS_INTERESTS/FeatureServer/0"
fLayer = FeatureLayer(t)
target_md = md.Metadata(fLayer.metadata)
# Note that the metadata is transformed from ArcGIS Metadata into the default output format for your ArcGIS Online Organizatoin
print(target_md.xml)

View solution in original post

4 Replies
daniel_marincounty
New Contributor II

I would also like to know how to do this 

0 Kudos
TorrinHultgren2
New Contributor III

Spent a while going back and forth on this with Esri Support, and ended up with several workarounds and an enhancement request.  The key takeaway is that today the arcpy.metadata module does not support hosted feature services, and the enhancement request is to address that.

Workarounds include:

Rolling your own with python "requests". This is pretty straightforward... until you want to edit non-public metadata records owned by enterprise accounts.  

import requests
# Example URL for top-level feature service
url = "https://services.arcgis.com/cJ9YHowT8TU7DUyn/arcgis/rest/services/FRS_INTERESTS/FeatureServer/info/metadata"
# Example URL for feature service layer
url = "https://services.arcgis.com/cJ9YHowT8TU7DUyn/ArcGIS/rest/services/FRS_INTERESTS/FeatureServer/0/metadata"

# Send an HTTP GET request to fetch the metadata XML
response = requests.get(metadata_url)

if response.status_code == 200:
    metadata_xml = response.text
    print(metadata_xml)
else:
    print(f"Error fetching metadata: {response.status_code}")

This code returns the raw ArcGIS Metadata, which is important. If you add format parameters (?format=default&f=xml) to the URLs above, it will run the XML through a stylesheet and while the result might then be standards-compliant, it won't be your original metadata, and may not be recognized by ArcGIS Pro.

Using the ArcGIS API for Python. This helps with access to non-public content, but doesn't appear to allow the source ArcGIS metadata to be returned for feature service layers, only the top level service metadata. 

# Example of retrieving Feature Service metadata:
from arcgis.gis import GIS
import arcgis
from arcgis.features import FeatureLayerCollection
from arcpy import metadata as md
import arcpy
gis = GIS('home')
test = "https://services.arcgis.com/cJ9YHowT8TU7DUyn/ArcGIS/rest/services/FRS_INTERESTS/FeatureServer" 
flc = FeatureLayerCollection(test, gis)
flcitem = arcgis.gis.Item(gis,flc.properties["serviceItemId"])
target_md = md.Metadata(flcitem.metadata)
print(target_md.xml)

# Example of retrieving Feature Service Layer metadata 
from arcgis.gis import GIS
from arcgis.features import FeatureLayer
from arcpy import metadata as md
gis = GIS('home')
t = "https://services.arcgis.com/cJ9YHowT8TU7DUyn/ArcGIS/rest/services/FRS_INTERESTS/FeatureServer/0"
fLayer = FeatureLayer(t)
target_md = md.Metadata(fLayer.metadata)
# Note that the metadata is transformed from ArcGIS Metadata into the default output format for your ArcGIS Online Organizatoin
print(target_md.xml)
daniel_marincounty
New Contributor II

Thank you so much for sharing (and saving me the trouble of contacting support 🤣)

0 Kudos
TorrinHultgren2
New Contributor III

Wanted to add that I tried grabbing a token from the gis object as documented here:

https://community.esri.com/t5/arcgis-api-for-python-questions/get-the-token-using-arcgis-python-api/...

But the result was "None" when used when used in ArcGIS Pro and the 'home' authentication option:

 

from arcgis.gis import GIS
gis = GIS('home')
token = gis._con._token
print(token)

None

 

Also while snooping around with the gis._con object, tried gis._con.get(metadata_url) which is supposed to automatically append any needed token by default. No luck:

Exception: A general error occurred: 'authInfo'

 

0 Kudos