Sign up ×
Geographic Information Systems Stack Exchange is a question and answer site for cartographers, geographers and GIS professionals. It's 100% free, no registration required.

I've got a script that takes a single input polygon feature, throws 10 buffers around it at tenths of a specified input distance, and then symbolises the output based on an existing layer file. Pretty simple.

However, the arcpy.MultipleRingBuffer_analysis operation is amazingly slow. It takes upwards of two minutes to generate the buffers, even for very basic polygon inputs - the same result can be had in about two seconds by using the buffer wizard tool. Problem is, the buffer wizard can't be accessed through arcpy.

So obviously it's possible to quickly generate multiple ring buffers - does anyone have any insight as to how the buffer wizard tool is doing it, and how that might be replicated in Python?

share|improve this question
It would be an interesting exercise to compile a chart of actual numbers, but it takes a great deal of time to just invoke arcpy and grab license, even before getting to any real work. I've seen import arcpy take 10s of seconds on its own. – matt wilkie Dec 19 '12 at 6:04
Just a note of caution: I've found the Multiple Ring Buffer wizard to be buggy. I have had situations where it failed to generate the rings as specified. However, the error does not seem to be consistent. I only noticed this problem since version 10. Prior to that it behaved itself. – MappaGnosis Dec 19 '12 at 9:43
@notaprogrammer Are you using ArcGIS 10.0 or 10.1? – dmahr Dec 19 '12 at 14:44
10.1, if that helps. – Nathaniel Dec 19 '12 at 22:42
@dmahr may be thinking along the lines of writing a Python Add-in for ArcMap which 10.1 opens up the opportunity for - I suspect that could be used to write a faster Multiple Ring Buffer for use in ArcMap but have not had chance to test it yet – PolyGeo Dec 20 '12 at 0:47

2 Answers 2

up vote 1 down vote accepted

While the buffer wizard is not exposed through ArcPy, geometries do expose the buffer method so the following works to create multiple ring buffers:

import arcpy

def MultiRingBuffer(ringDistance, ringCount, inputLayer, outputLayer):
    buffers = []

    cursor = arcpy.SearchCursor(inputLayer)
    for inputFeature in cursor:
        sourceOid = inputFeature.getValue("OBJECTID")
        currentBuffers = dict()
        prevBuffer = inputFeature.Shape

        for multiple in range(1, ringCount + 1):
            distance = multiple * ringDistance
            bufferedGeom = inputFeature.Shape.buffer(distance)
            bufGeom = bufferedGeom.difference(prevBuffer)
            prevBuffer = bufferedGeom
            row = dict()
            row["sourceOid"] = sourceOid
            row["distance"] = distance
            row["SHAPE"] = bufGeom
            currentBuffers[distance] = row
    del cursor

    cursor = arcpy.InsertCursor(outputLayer)
    for ringBuffers in buffers:
        for feature in ringBuffers.values():
            row = cursor.newRow()
            for k in feature.keys():
                if k == "SHAPE":
                    row.Shape = feature[k]
                    row.setValue(k, feature[k])
    del cursor

if __name__ == '__main__':
    MultiRingBuffer(10, 10, "c:\\temp\\test.gdb\\buffertest", "c:\\temp\\test.gdb\\bufferout")

For each source feature, we create a dictionary to store each ring buffer. Each of these buffers is a dictionary with a few values - the source OID, the distance, and the buffer geometry. We then create an insert cursor and create features in the output table for each ring buffer of each input feature.

Edit: I have tested this and with 3 simple features, where the gp tool takes over a minute, this script takes ~1s once arcpy has finished importing.

Edit 2: Fixed a couple of bugs - firstly, the difference call was removing the previous ring rather than all previous rings. Secondly, I wasn't adding the ring to the currentBuffer so it wasn't getting added later...

Edit 3: Handled the shape field not being 'SHAPE' in the output featureclass. Added cleanup of cursor objects.

share|improve this answer
Thanks for this, it looks promising. I couldn't get any output though. I can get things to a point where it looks like the script is running (it runs very quickly, as you said), but nothing appears to be altered in the input or output feature classes. How exactly did you set up your test, so that I can try to replicate your results? – Nathaniel Jan 23 at 6:12
Thank you, there were a couple of bugs in there. In the loop that actually calls Shape.buffer I've made a couple of changes - first, to separate the buffer and difference, so the plain buffered geometry can be used for subsequent differences, and secondly to actually add the row dictionary to the currentBuffers dictionary – Martin Wilkerson Jan 23 at 10:15
It's still falling over for me at the last row.setvalue line. I can see what it's supposed to do, but I don't know enough Python to fix it. Any ideas? – Nathaniel Jan 28 at 7:05
Could be that your shape field isn't called 'SHAPE'? It certainly doesn't have to be, I only used that as a shortcut. Could you post the error it's giving please? And I'll edit the above to use the row's shape property just in case that's it (and it's more correct anyway). – Martin Wilkerson Jan 29 at 9:03
It could also be missing fields in the output feature class - it needs to have be a polygon feature class with two long integer fields called 'sourceOid' and 'distance'. Change the row dictionary entries in the first loop to change what attributes are set in the output feature class. – Martin Wilkerson Jan 29 at 9:11

Unfortunately, the Buffer wizard (and its options) are not exposed in ArcObjects or ArcPy.

I'm trying to think of ways around this. One cool thing about the Buffer wizard is that you can use an optimized coordinate system at either a selected feature set / entire dataset or feature level. If you're using the former (not the feature-optimized), and your data is using a geographic coordinate reference system, you might try projecting your data into a projected coordinate system, then running the Buffer Tool.

Note: I work for Esri.

share|improve this answer
Hi @mkennedy - thanks for your comment. I don't know what an optimized coordinate system is, but I am using features that have been projected into a proj. coord. system. If you have any sway in this at ESRI, can you ask why the Buffer Wizard a) is so buried in tools so that only an exhaustive Google search eventually leads to an Esri blog post that reveals its existence? and b) why can't it just retain the other fields in the outputs from the input features like almost every other tool? – SharonB Sep 9 '13 at 16:11

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.