Python script never terminates

3879
14
08-28-2015 04:40 PM
RobertStevens
Occasional Contributor III

Can someone divine why the attached python script never terminates?

I am running with ArcGIS10.3.1 basic.

When I run this using 32-bit python it gets to the last layer

and the terminates with a segmentation violation.

With a 64-bit python it never terminates.

The program runs fine on other maps I have, but

one in particular gives this problem. AFAIK

the map in question is not in any relevant

sense different from those on which the

script runs ok.

Tags (2)
0 Kudos
14 Replies
DanPatterson_Retired
MVP Emeritus

zips don't open easily on iThingys, if the script isn't too long, copy, paste and format it using the python​ syntax highligher accesses with the >> bu​tton using the advanced editor

0 Kudos
RebeccaStrauch__GISP
MVP Emeritus

I've posted you script, as is (after the unzip), and it looks like your indentation is off onmany of the likes.  36, 37, and 55 have an extra space in front.  And some of the if and elif:  statements don't seem to be indented at all, so thinks wouldn't execute....which may be why the program doesn't end for some mxd's.  If these are correct on you side, then it may be something happened in the zip file.  Use Posting Code blocks in the new GeoNet​  to post the corrected copy of your code.

I've gone a completely different route for updating my broken links, since the .sde and .ags connections needed special handling.  So I'll be interested if you code (once fixed) handles all those.  My process reads from an excel/ (actually csv) file and can change paths, and feature class types, if needed.  Seems to be working now, but running a test this weekend.  Then I need to clean up the code a bit.  You code is much shorted than mine, but not sure if I understand what it does complete (I'm not familiar with the OptionParser or glob for that matter).

import glob
import os
import sys
import arcpy
import arcpy.mapping as mapping
from optparse import OptionParser

# Previous invocations of this script were used to effect the following conversions
# from Program Files (x86)/ArcGIS/Desktop10.0/Business Analyst/US/Data/
# to   Business Analyst/2011Data/
# from RLIS_201402  to  RLIS
# from RLIS_201402  to  RLIS_WebMercator

parser = OptionParser()
parser.add_option("-f", "--fix", action="store_true", dest="f",
                  default=False,help="fix the source name")
parser.add_option("-o", "--old-src", action="store", dest="o",
                  default="RLIS-201402",
          help="the old source file name, or part of a name")
parser.add_option("-n", "--new-src", action="store", dest="n",
                  default="RLIS",
          help="the new source file name, or part of a name")

(options, args) = parser.parse_args()

old_src = options.o
new_src = options.n

def fixLayer(lyr):
    lyrModified = False
    if lyr.isFeatureLayer:
    print lyr.name
    if old_src in lyr.dataSource:
        print "\t\t" + lyr.dataSource
    if options.f:
         lyrModified = True
         lyr.findAndReplaceWorkspacePath(old_src,new_src,False)
    return lyrModified

def fixMap(mxd):
    mxdModified = False
    # loop thru all data frames in the map
    dataFrames = mapping.ListDataFrames(mxd, '')
    for frame in dataFrames:
        print "\tframe " + frame.name
        # get all layers in this data frame
        layers = mapping.ListLayers(mxd, '', frame)
        # loop thru all layers in the data frame
    print layers
    for lyr in layers:
        lyrModified = fixLayer(lyr)
        if lyrModified:
        mxdModified = True
    if mxdModified:
         mxd.save()

def fixit(fullPath,fileName):
    desc = arcpy.Describe(fullPath)
    if desc.datatype == "MapDocument":
    print fileName
    mxd = mapping.MapDocument(fullPath)
    fixMap(mxd)
    del mxd
    elif desc.datatype == "Layer":
    print fileName
    lyr = mapping.Layer(fullPath)
    if fixLayer(lyr):
        lyr.save()
    del lyr

for arg in args:
    if os.path.isdir(arg):
    for fileName in os.listdir(arg):
        fullPath = os.path.join(arg, fileName)
        fixit(fullPath,fileName)
    elif os.path.isfile(arg):
    fixit(arg,arg)
    else:
    print arg + " is not a map, nor a layer, nor a directory"
RobertStevens
Occasional Contributor III

yes, you are right.

I don't know how that happened.

It was correct at one time.

I have no idea what Python would do with that

but I will correct it and retry.

0 Kudos
RebeccaStrauch__GISP
MVP Emeritus

Are you using a good IDE that shows Python syntax errors?  There are many....I use and like Wing.  I use the Pro version but there is a free one too.  But many others.  It would bark at the extra space and would also give you an error when there is a "elif" with nothing to do, etc.   Just a suggestion if you aren't using one.  If it was in the .zip....no clue.

0 Kudos
RobertStevens
Occasional Contributor III

I fixed the indentation problems, and Wing seems to say all is OK.

But the behavior is unchanged.

0 Kudos
JoshuaBixby
MVP Esteemed Contributor

If the code works fine on all other maps, and only crashes on one map, something is likely off with that one map.  I have run into issues where MXDs are partially corrupt, not too corrupt for ArcMap to open but corrupt enough that ArcPy scripts will crash.  Have you run DocDefragmenter or MXDDoctor on the problem map?  If not, it might be worth seeing if running either of those makes a map that doesn't crash.

If the MXD is healthy and defragged, there might be a data source in the map that is exposing a bug with ArcPy.

0 Kudos
RebeccaStrauch__GISP
MVP Emeritus

And to add what Joshua suggested....a SaveAs sometimes fixes slightly corrupted or bloated MXDs.

Do you have any .sde, groups, arcgis-server, etc connections in this mxd?  And if so, does your code take those different items into consideration?   im not sure if hitting one of those items would not let your script terminate, but it know they can/will cause issues when trying to auto fix broken links.​

0 Kudos
RobertStevens
Occasional Contributor III

I have run the MXD Doctor and the Defrag utility all with no effect.

No the map in question does not have any .sde or server connections

-- all the data is local.

One other thing I should say is that I am  presently running this script

to identify layers using a particular dataset. I am not changing anything

(so the -f option is false).

Just as an aside: this Python interface of arcpy is so slow. One notices

this also when invoking Python tools from within ArcGIS. Even to bring

up the dialogue screen is sluggish -- 10,15 even sometimes 20 seconds.

Given that Windows itself running under Parallels on my MAcbook Pro

takes a mere 5 seconds to startup, those numbers are astonishing.

0 Kudos
RobertStevens
Occasional Contributor III

The code that Rebecca kindly formatted did not properly show indentation

possibly because tabs and spaced were intermingled.

(Though there were the 3 errors she mentioned, since fixed).

I have re-posted the script here with the proper indentation.

import glob
import os
import sys
import arcpy
import arcpy.mapping as mapping
from optparse import OptionParser


# Previous invocations of this script were used to effect the following conversions
# from Program Files (x86)/ArcGIS/Desktop10.0/Business Analyst/US/Data/
# to  Business Analyst/2011Data/
# from RLIS_201402  to  RLIS
# from RLIS_201402  to  RLIS_WebMercator


parser = OptionParser()
parser.add_option("-f", "--fix", action="store_true", dest="f",
                  default=False,help="fix the source name")
parser.add_option("-o", "--old-src", action="store", dest="o",
                  default="RLIS-201402",
                  help="the old source file name, or part of a name")
parser.add_option("-n", "--new-src", action="store", dest="n",
                  default="RLIS",
                  help="the new source file name, or part of a name")


(options, args) = parser.parse_args()


old_src = options.o
new_src = options.n


def fixLayer(lyr):
    lyrModified = False
    if lyr.isFeatureLayer:
        #print lyr.name
        if old_src in lyr.dataSource:
            print "\t\t" + lyr.dataSource
        if options.f:
            lyrModified = True
            lyr.findAndReplaceWorkspacePath(old_src,new_src,False)
    return lyrModified


def fixMap(mxd):
    mxdModified = False
    # loop thru all data frames in the map
    dataFrames = mapping.ListDataFrames(mxd, '')
    for frame in dataFrames:
        print "\tframe " + frame.name
        # get all layers in this data frame
        layers = mapping.ListLayers(mxd, '', frame)
        # loop thru all layers in the data frame
        #print layers
        for lyr in layers:
            lyrModified = fixLayer(lyr)
            if lyrModified:
                mxdModified = True
    if mxdModified:
        mxd.save()


def fixit(fullPath,fileName):
    desc = arcpy.Describe(fullPath)
    if desc.datatype == "MapDocument":
        print fileName
        mxd = mapping.MapDocument(fullPath)
        fixMap(mxd)
        del mxd
    elif desc.datatype == "Layer":
        print fileName
        lyr = mapping.Layer(fullPath)
        if fixLayer(lyr):
            lyr.save()
        del lyr


for arg in args:
    if os.path.isdir(arg):
        for fileName in os.listdir(arg):
            fullPath = os.path.join(arg, fileName)
            fixit(fullPath,fileName)
    elif os.path.isfile(arg):
        fixit(arg,arg)
    else:
        print arg + " is not a map, nor a layer, nor a directory"


exit(0)