Assuming most layers in most maps will have data sources, and hence spatial references, a try/except block will perform the best. That has been the case historically but especially since Python 3.11 with the implementation of "zero-cost" exceptions.
From What’s New In Python 3.11 - Python 3.11.8 documentation:
“Zero-cost” exceptions are implemented, eliminating the cost of try statements when no exception is raised. (Contributed by Mark Shannon in bpo-40222.)
For me personally, I don't like the aesthetics of try/except blocks so I tend to avoid them unless necessary. A common sylistic argument for using try/except blocks is that they are explicit, and PEP 20 – The Zen of Python | peps.python.org states, "Explicit is better than implicit." I actually agree that explicit is better than implicit and that try/except blocks are explicit, but it doesn't mean one has to use a try/except block to be explicit.
The Look Before You Leap (LBYL) code in another answer
if arcpy.Describe(lyr).dataType in ['RasterLayer','FeatureLayer']:
SRID = arcpy.Describe(lyr).spatialReference.PCSCode
is implicit because it uses the data type of the layer to infer whether the describe object has a spatial reference before calling a spatial reference property. A more explicit LBYL approach is to use hasattr - Built-in Functions - Python 3.x documentation to check whether the describe object has a spatial reference.
desc = arcpy.Describe(lyr)
SRID = desc.spatialReference.factoryCode if hasattr(desc, 'spatialReference') else "N/A"
A couple other comments on the original code:
arcpy.Describe
is an expensive function call. It is much better for performance and maintainability to call it once and store it in a variable, e.g., desc = arcpy.Describe(lyr)
, than to call it over and over again.
spatialReference.factoryCode
applies to both geographic and projected data sets, so code will be more portable using it than PCSCode
or GCSCode
. Also, WKID is typically what people are after then calling PCSCode
or GCSCode
.