|
POST
|
Am I missing something here? Why wouldn't you be able to use the 'ExportXMLWorkspaceDocument_management()' function in arcpy? To export the schema with the data contents, just set the export_type argument to 'Data'.
MyGDB = r"C:\MyGIS\MyGDB.gdb"
ResultXML = r"C:\MyGIS\MyGDBXML.xml"
arcpy.ExportXMLWorkspaceDocument_management (MyGDB, ResultXML, "DATA", "BINARY", METADATA)
If you need to do this for a bunch of GDBs, then just populate them all in a list and loop through the list.
... View more
02-02-2014
09:15 AM
|
0
|
0
|
2559
|
|
POST
|
I could be wrong but I dont think that's possible. From the ArcGIS 10.2 Help arcticle on accessing licenses from python, the problem you're going to encounter is that when you import arcpy, it needs an ArcGIS License. So if you're using a License Server, you're going to need to establish a connection to that License Server and the Licensing Service on that machine somehow. You could try using the legacy SetProduct function, but again, how would you connect to the License Server? In the case of a single use license, you would probably need an additional license just for your mac. I do wonder if you could just copy over the entire ArcGIS python library and put it into your own Python install directories and import them within your IDE. You wouldn't be able to debug or run any of it but you could theoretically at least get the intellisense going. It would be interesting to know if that works. Seems to me in the end though, since you can't run anything Mac-side you'd be better off running Bootcamp or Parallels to get back to a Windows OS.
... View more
01-29-2014
10:43 AM
|
0
|
0
|
1001
|
|
POST
|
A helpful hint someone gave me when I first starting coding was to write nothing but comments before ever writing a single line of code. It accomplishes a few things. First, it ensures your code is always well documented. Secondly, it allows you to easily determine the intent of a line of code without having to decipher all of the variables and arguments, logic and flow in your code in order to understand the intent. Third, it allows you to quickly see how you can improve your code down the road. As you get better, you'll realize more efficient ways of doing things and you'll be able to easily see that in your code if you have a comment telling you the plain text intent and a line of code showing how you did it in the past. Print statements are always really helpful too because you can watch your code process in the Python window and see where things get hung up, take too long or perhaps flow in a manner you didn't expect. I use both of those methods constantly it's made life much easier.. I took a closer look at your code and found that your lyr.replaceDataSource functions appeared to be indented too far. I also commented up some places where changes could be made to make things more efficient. A Syntax Check in your IDE should catch that. One odd thing I did notice is that the path you're providing in your replaceDataSource function looks like an SDE Connection. If that's the case, you need to change the parameter from Shapefile Workspace to SDE. Give it a shot and let us know how it goes.
import arcpy
from arcpy import env
# Create a variable called Workspace to hold the workspace path
# Doing it this way allows us to continually reference the 'workspace' variable
# whenever we want to get to that path. Also, use the raw string literal format to
# reference the path. The way you had it before is ok, but using forward slashes can
# cause issues with inconsistencies in future path definitions, especially when joining
# or concatenating paths.
workspace = r"C:\GIS\MAPBOOK\Proposed Zoning Book"
print "Workspace = " + str(workspace)
# Now set the Workspace by referencing the path contained in the 'workspace' variable
arcpy.env.workspace = workspace
print "Environment Workspace set to: " + str(workspace)
# Set the overwriteOutput environment parameter to True
arcpy.env.overwriteOutput = True
print "Overwrite Outputs: True"
# Create a list of MXDs in the workspace and populate the results in the variable
# 'mxdList'
mxdList = arcpy.ListFiles("*.mxd")
# Validate that results were actuall populated in the 'mxdList' variable and that it is
# not empty
# If the number of items (len) contained in the mxdList is equal to 0:
if len(mxdList) == 0:
# Raise an error because there are no MXDs in the workspace!!
raise Exception("No MXDs were found in the workspace!")
# Otherwise:
else:
# Do nothing and continue
pass
# Inform how many MXDs were returned from the Workspace and populated in the 'mxdList'
print "Found " + str(len(mxdList) + " MXDs in the Workspace")
# For each mxd populated in the mxdList:
for mxd in mxdList:
# Change the variable name to 'targetMXD' because you already have an 'mxd'
# variable instantied as the current mxd being executed against in the loop.
# This could cause problems with execution and at the least, can be confusing
targetMXD = workspace + "//" + mxd
# For each layer in the 'targetMXD'
for lyr in arcpy.mapping.ListLayers(targetMXD)[0]:
# If the given 'lyr' is "PROPOSED ZONING"
if lyr.name == "PROPOSED ZONING":
print "Found Layer with name: " + str(lyr.name) + ". Replacing Datasource..."
# Replace the Layer's datasource with the below
lyr.replaceDataSource("C:/Users/t***a/AppData/Roaming/ESRI/Desktop10.1/ArcCatalog/DSD15_SQLEXPRESS.gds/DSD/DSD.DBO.MUNICIPALITY", "SHAPEFILE_WORKSPACE", "DSD.DBO.FUTURE_LAND_USE_ZONING")
print "Success"
# Otherwise if the given 'lyr.name' is "CITY LIMITS"
elif lyr.name == "CITY LIMITS":
print "Found Layer with name: " + str(lyr.name) + ". Replacing Datasource..."
# replace the given Layer's Datasource with the below
lyr.replaceDataSource("C:/Users/t***a/AppData/Roaming/ESRI/Desktop10.1/ArcCatalog/DSD15_SQLEXPRESS.gds/TonyOneWay/TonyOneWay.DBO.Canyon_Features", "SHAPEFILE_WORKSPACE", "TonyOneWay.DBO.City_Limits")
print "Success"
print "Successfully updated data sources"
mxd.save()
Update: Wow. I stopped to take a call and this post progressed quick!!!
... View more
01-29-2014
09:55 AM
|
0
|
0
|
1465
|
|
POST
|
Looks like you missed the parenthesis to close out the ListLayers argument.
for lyr in arcpy.mapping.ListLayers(mxd[0]:
Use this instead:
for lyr in arcpy.mapping.ListLayers(mxd)[0]:
... View more
01-29-2014
05:56 AM
|
0
|
0
|
1813
|
|
POST
|
Within your Layer Loops, you're interrogating the Layer.name property.
for lyr in arcpy.mapping.ListLayers(mxd):
if lyr.name == "PROPOSED ZONING":
lyr.replaceDataSource("C:/Users/t***a/AppData/Roaming/ESRI/Desktop10.1/ArcCatalog/DSD15_SQLEXPRESS.gds/DSD/DSD.DBO.MUNICIPALITY", "SHAPEFILE_WORKSPACE", "DSD.DBO.FUTURE_LAND_USE_ZONING")
for lyr in arcpy.mapping.ListLayers(mxd):
if lyr.name == "CITY LIMITS":
lyr.replaceDataSource("C:/Users/t***a/AppData/Roaming/ESRI/Desktop10.1/ArcCatalog/DSD15_SQLEXPRESS.gds/TonyOneWay/TonyOneWay.DBO.Canyon_Features", "SHAPEFILE_WORKSPACE", "TonyOneWay.DBO.City_Limits")
print "Successfully updated data sources"
Problem is, your ListLayers function did not return Layer Objects so you can't interrogate the Layer.name property. Check out the third line of the Discussion section on the ListLayers Help Document. In order for the ListLayers function to return a Layer Object, you must use an index value on the List like this:
for lyr in arcpy.mapping.ListLayers(mxd)[0]:
if lyr.name == "PROPOSED ZONING":
lyr.replaceDataSource("C:/Users/t***a/AppData/Roaming/ESRI/Desktop10.1/ArcCatalog/DSD15_SQLEXPRESS.gds/DSD/DSD.DBO.MUNICIPALITY", "SHAPEFILE_WORKSPACE", "DSD.DBO.FUTURE_LAND_USE_ZONING")
for lyr in arcpy.mapping.ListLayers(mxd)[0]:
if lyr.name == "CITY LIMITS":
lyr.replaceDataSource("C:/Users/t***a/AppData/Roaming/ESRI/Desktop10.1/ArcCatalog/DSD15_SQLEXPRESS.gds/TonyOneWay/TonyOneWay.DBO.Canyon_Features", "SHAPEFILE_WORKSPACE", "TonyOneWay.DBO.City_Limits")
print "Successfully updated data sources"
Crazy, I didn't know that myself until I investigated your issue. I've just always done it out of habbit.
... View more
01-28-2014
02:21 PM
|
0
|
0
|
1813
|
|
POST
|
Can you post the script that you are running as a scheduled task?
... View more
01-28-2014
02:02 PM
|
0
|
0
|
999
|
|
POST
|
The first problem I see here is that you are using double backslashes inside of a raw string literal. A raw string literal is the exact string written inside of quotes when prefaced with an 'r'. When you specify a path with as a raw string literal, you don't need the double-backslashes because python is going to use the exact string specified within the quotes. Just use a single backslash, the same as you would in Windows to navigate to a specific path. For me, this is why I always specify a path as a raw string literal. I can use the same formatting to define a path as Windows. If you don't use the raw string literal prefix (r), then you do need to use double-backslashes because a single backslash is an escape in python. If you use a single backslash without the raw string literal prefix, you will likely end up escaping some of the characters in your path. As a result of having those double-backslashes inside of a raw string literal, when you perform the 'os.path.join()' function, the return contains an excessive number of backslashes. Take this example:
>>> folderPath = r"C:\\01Working_Directory\\LandscapeMaps"
>>> file = "MyGISFile"
>>> os.path.join(folderPath, file)
'C:\\\\01Working_Directory\\\\LandscapeMaps\\MyGISFile'
>>>
That's a lot of backslashes. The last part where the file was joined to the folderPath is ok because the 'os.path.join()' inserted the appropriate seperator when executing the join. Replacing the double-backslashes in your 'folderPath' variable with single backslashes should resolve the issue. In regards to fixing your broken data sources, it is completely possible. You already know how to loop through a list of MXDs, so now it's just a matter of invoking the appropriate functions to list the broken data sources, loop through that list and replace their data sources. Take a look at this help article. It should point you in the right direction.
... View more
01-28-2014
12:35 PM
|
0
|
1
|
2306
|
|
POST
|
Good thread. Is their an easy way to do this where you want to do it to all MXDs in a folder? Sure, you could just modify the existing code with the listfiles() function and leverage the wildcard argument to identify MXDs in a given folder.
# Import the arcpy module
import arcpy
# Identify the path to the Layer File you want to insert on disk.
InsertLayer = arcpy.mapping.layer(r"C:\MyGIS\Layers\TheLayerFileToInsert.lyr")
# Identify the Folder containing the MXDs you want to insert the 'InsertLayer' into
MXDsFolder = r"C:\MyGIS\MXDsFolder"
# Set the Environment Workspace to the MXDs Folder so that the 'ListFiles()'
# function will search this folder for MXDs when called
arcpy.env.workspace = MXDsFolder
# Call the 'arcpy.ListFiles()' function and invoke the wildcard parameter to only
# return MXDs from the folder. Populate the results in the variable 'MXDsList'
MXDsList = arcpy.ListFiles("*.mxd")
# Loop through each MXD in the 'MXDsList'
for MXD in MXDsList:
# Establish the current MXD as the 'TargetMXD' to insert the Layer into
TargetMXD = arcpy.mapping.MapDocument(MXDsFolder + "\\" + str(MXD))
# Get a reference to the first dataframe in the Target MXD
TargetDF = arcpy.mapping.ListDataFrames(TargetMXD)[0]
# Add the Layer to the TargetMXD
arcpy.mapping.AddLayer(TargetDF, InsertLayer, "TOP")
# Save the MXD
TargetMXD.save()
print "Complete"
... View more
01-28-2014
05:39 AM
|
0
|
0
|
2306
|
|
POST
|
Isn't that what a debugger is for? You could do this, but it's a terrible idea and will slow your program down by orders of magnitude: import inspect
import sys
def tracefunction(frame, event, arg):
if event == "line":
info = inspect.getframeinfo(frame)
fname, lineno, fn = info.filename, info.lineno, info.function
with open(fname, 'rb') as f:
line = [line.rstrip() for line in f][lineno - 1]
print "Function: {} (in file {}:{}) | {}".format(fname, fn, lineno, line)
return tracefunction
def registertracefunction():
sys.settrace(tracefunction)
registertracefunction()
def mainfunction():
for x in xrange(10):
print x * 5
if __name__ == "__main__":
mainfunction() That is, paste the code up through registertracefunction() line to the top of your script and it will print out every line it's on. Thanks Jason, I figured that something like this would degrade performance. Debugging would be a good option except Python Addins don't lend themselves to debugging quite as well as something like a Script tool and I was really hoping to not have to resort to inserting print statements on every other line.
... View more
01-28-2014
04:35 AM
|
0
|
0
|
3852
|