I have a script with several functions in it that use arcpy.ListFeatureClasses(). I'm having trouble pointing each function at the proper workspace. It seems like if I change the workspace inside a function then all the function calls after that use the wrong workspace. But if I set the arcpy.env.workspace inside each function it throws errors saying
''ERROR 000732: Input Table: filename does not exist or is not supported''
How do I point each function at its proper workspace? Images of a couple of the functions are below:
Do you know anything about functions and workspacesJoe Borgione?
After a quick look at your functions, you might set and then pass the workspace to your function:
def someFunction(ws):
workspace = ws
# more code
return something
workspace1 = r'C:\Some\Path\to\data1.gdb'
x = someFunction(workspace1)
workspace2 = r'C:\Some\Path\to\data2.gdb'
y = someFunction(workspace2)
Is this what you are looking for?
James- Along with what @Randy_Burton suggests, using
import arcpy
arcpy.env.workspace = r'X\some\path\to\your.gdb'
sets it explicitly. With ListFeatureClasses and ListTables() both need the workspace set as shown above, and I don't think either of them take an argument. If you are going to set a workspace with env and copy data to a different out workspace, just set a variable:
arcpy.env.workspace = r'T:\GIS Documents\MOW\SDE_Surrogate.gdb'
outWS = r'T:\GIS Documents\MOW\ClientCount.gdb'
fields = ['Month','Year']
arcpy.SplitByAttributes_analysis('MasterDelivery2018',outWS,fields)
Notice how line one sets the env while line 2 sets where I want the output of SplitByAttributes() to go.
Another example:
arcpy.env.workspace = r'T:\GIS Documents\MOW\ClientCountSum2.gdb'
outWS = arcpy.env.workspace
inFeatures = r'I:\GIS\ArcSDE\SuperUser\is\slco@slcopub.sde\slcopub.SLCO.Administration\slcopub.SLCO.ZipCodes'
layerName = 'zipLayer'
joinField1 = 'ZIP_CD'
joinfield2 = 'FIRST_Residential_Zipcode'
for t in arcpy.ListTables():
try:
joinTable = t
outFeature = '{}\{}joined'.format(outWS,t)
arcpy.MakeFeatureLayer_management (inFeatures, layerName)
arcpy.AddJoin_management(layerName, joinField1, joinTable, joinfield2)
arcpy.CopyFeatures_management(layerName, outFeature)
print('Success: created month feature class')
except Exception as err:
print('Error')
print(err)
Line 2 sets the outWS explicitly so I can use it a little later in line 11 where I name the out feature class using the original table name with the word 'joined' pasted to the end of it.
and finally, one more example I just wrote for the same meals on wheels project I working on:
arcpy.env.workspace = r'T:\GIS Documents\MOW\ClientCountSum2.gdb'
target = r'T:\GIS Documents\MOW\SDE_Surrogate.gdb\ClientCountByZip'
for x in arcpy.ListFeatureClasses():
arcpy.Append_management(x,target,'NO_TEST')
Glad to see you are writing python at your new job!
Thanks for the tips Joe! After some testing today I've come to the conclusion that I am having issues with the environment Spyder is set up in. I was messing with the PYTHONPATH and PATH last week to try and work with QGIS tools as well and now I'm getting unexpected behavior from Spyder IDE, which is installed in the cloned environment. My functions run great in IDLE and the ArcGIS Pro python window but not in Spyder.
It sure is fun stuff to try and figure out /s. I re-cloned my environment and downloaded spyder into that but I am still getting the same error. Not sure what my next move is.
Shoot.... You lost me at QGIS ... 😉
I guess you may want to go back and reset PYTHONPATH and PATH and start over?
It seems like if I change the workspace inside a function then all the function calls after that use the wrong workspace.
Yep. If you change the workspace, you need to change it back.
What I do is use a context manager to temporarily set arcpy.env values and then automatically reset them to the original values.
from contextlib import contextmanager
import arcpy
@contextmanager
def env(**kwargs):
""" context manager for arcpy.env vars """
try:
# Copy old env then set new values
old_env = {}
for key, val in kwargs.items():
old_env[key] = getattr(arcpy.env, key)
setattr(arcpy.env, key, val)
yield
finally:
# Restore old values
for key, val in old_env.items():
setattr(arcpy.env, key, val)
def some_function():
print(arcpy.env.workspace)
if __name__ == '__main__':
arcpy.env.workspace = 'C:/Temp'
some_function()
with env(workspace='D:/GIS'):
some_function()
some_function()
with env(workspace='G:/Work'):
some_function()
some_function()
This outputs:
C:/temp
D:/GIS
C:/temp
G:/Work
C:/temp
It's even easier these days with arcpy.EnvManager
with arcpy.EnvManager(workspace=r"D:\Data"):
some_function()
Why troubleshoot a problem with legacy ArcPy functions when you can use newer, better ArcPy functions. See Walk—ArcGIS Pro | Documentation