I created an ArcMap Python add-in using ArcGIS 10.1 to open a webpage after the map is clicked. It opens the page but then ArcGIS crashes.

import arcpy
import pythonaddins
import webbrowser
class ToolClass2(object):
    """Implementation for TEST_addin.tool (Tool)"""
    def __init__(self):
        self.enabled = True
    def onMouseDownMap(self, x, y, button, shift):

    df = arcpy.mapping.ListDataFrames(mxd)[0]
    pythonaddins.MessageBox("Long" + " " + str(x) + '\n'+ "Lat"+ " " + str(y), 'Coordinates', 0)
    path = 'http://pol.pictometry.com/en-us/php/default.php?lat=' +str(x) +'&lon=' + str(y)+'&v=p&o=n&type=or&level=n'
  • 1
    Your indentation looks astray (mxd at same level as def) - perhaps fix it in Question or code, whichever applies. When you say Arc crashes do you mean it bails with a Serious Application Error or something else? – PolyGeo Feb 1 '13 at 8:04
  • The above threaded method works fine for me, but I have to wait some 20 seconds before the browser actually opens which to most users is a crash! Is this speed correct? – user14853 Feb 4 '13 at 17:39
  • @TonyCollins, The browser opens within a few seconds on the computers I have tried. I am not sure what is going on in your situation. How long does it take to normally open a web browser? – blah238 Feb 4 '13 at 17:51

@BMac's code also crashes my ArcMap 10.1 SP1 installation.

This code works properly however:

import arcpy
import pythonaddins
import webbrowser
from threading import Thread

def OpenBrowserURL():
    url = 'http://www.google.com'

class OpenWebBrowserButtonClass(object):
    """Implementation for WebBrowserAddIn.openWebBrowserButton (Button)"""
    def __init__(self):
        self.enabled = True
        self.checked = False
    def onClick(self):
        t = Thread(target=OpenBrowserURL)

I call the same function from a new thread. Python add-in classes probably run on the UI thread by default and maybe there is some race condition or other issue causing ArcMap to crash, but if called from another thread it works.

Update: I just saw an ArcGIS Team Python blog post about this:

os.startfile and webbrowser.open are two very useful functions in the Python library. However, due to some conflicts in the way the Windows libraries expect to be called, they can fail or crash when called within ArcGIS for Desktop in an add-in script or geoprocessing script tool (see the Remarks section on this MSDN reference page).

import functools
import os
import threading
import webbrowser

# A decorator that will run its wrapped function in a new thread
def run_in_other_thread(function):
    # functool.wraps will copy over the docstring and some other metadata
    # from the original function
    def fn_(*args, **kwargs):
        thread = threading.Thread(target=function, args=args, kwargs=kwargs)
    return fn_

# Our new wrapped versions of os.startfile and webbrowser.open
startfile = run_in_other_thread(os.startfile)
openbrowser = run_in_other_thread(webbrowser.open)

The local functions startfile and openbrowser will be made available, which have the same parameters as the versions in the standard library but will run in another thread and therefore work as expected.

Somewhat related: ArcGIS 10.1 Python AddIn Using Multiprocessing crashes ArcMap?

  • 2
    Hopefully the MSDN reference gives clarity. Not a race condition, but a COM environment issue in that thread. ArcGIS uses one COM threading model, the Windows Explorer component that gets called to open URLs/files uses another. – Jason Scheirer Oct 28 '13 at 22:49

I opened the ArcMap python window and was able to run the following code successfully:

import webbrowser
url = 'http://www.google.com'

However, I end up with the same issue when running as a python add-in. Closes/crashes ArcMap and opens the browser. Could be a bug in the add-in module or we need to rename our button to "Open browser and crash ArcMap". Sounds like you might need to call ESRI support to report a possible bug.

Sample Python add-in that crashes ArcMap:

import arcpy
import pythonaddins
import webbrowser

def OpenBrowserURL():
    url = 'http://www.google.com'

class OpenMetadata(object):
    """Implementation for TestAddins_addin.button1 (Button)"""
    def __init__(self):
        self.enabled = True
        self.checked = False
    def onClick(self):
  • Odd thing...occured – Kyle Feb 2 '13 at 1:46

I just ran across this issue. I wasn't able to stabilize the situation with blah238's remedy, but I did seem to find success with using Python's subprocess module. Here's my code:


class OpenURL(object):
    """Implementation for OpenURL_addin.button (Button)"""
    def __init__(self):
        self.enabled = True
        self.checked = False
    def onClick(self):
        url = "http://mywebsite.com"
        import subprocess

        #Set up the subprocess components
        python_path = r"C:\Python27\ArcGIS10.1\python.exe"
        python_script = r"C:\ArcGIS_AddIns\PythonAddIns\Tools\GIS_Locate\Install\OpenWebBrowser.py"

        #Now call the script and pass in the necessary variables
        subprocess.call([python_path, python_script, url]) 

import sys
import webbrowser

url = sys.argv[1]

All here is an implementation I just got working. Most of this was taking code from other posts and trying to make the tool more dynamic. Hopefully it helps someone in the future who is trying to do the same thing.

import arcpy, pythonaddins, json, webbrowser, threading
#   Written by : Ken Carrier
#   Date       : 03/12/2015
#   Pictometry Connect python add-in tool. Will convert map click to current
#   spatial reference coordinates to WGS_84 coordinates. Then opens Pictometry
#   Connect in default web browser in a thread separate from ArcMap.

class PictometryConnectTool(object):
    """Implementation for Pictometry_addin.tool (Tool)"""
    def __init__(self):
        self.enabled = True
        self.shape = "NONE" # Can set to "Line", "Circle" or "Rectangle" for interactive shape drawing and to activate the onLine/Polygon/Circle event sinks.

    def onMouseDownMap(self, x, y, button, shift):
        # Get reference to current map document.
        # Get reference to active dataframe.
        df = arcpy.mapping.ListDataFrames(mxd)[0]
        # Get spatial reference from dataframe.
        sr_df = df.spatialReference.PCSCode
        # Set spatial reference object for current spatial reference.
        sr_sp = arcpy.SpatialReference(sr_df)
        # Set spatial reference object for Pictometry WKID: 4326.
        sr_wgs = arcpy.SpatialReference(4326)
        # Get point geometry object from mouse click
        # Reproject X&Y coordinates from map click to WKID: 4326.
        prj_pt = pt.projectAs(sr_wgs)
        # Read the returned objects JSON string
        data = json.loads(prj_pt.JSON)
        # Parse JSON get reprojected X coordinate.
        wgsX = data["x"]
        # Parse JSON get reprojected Y coordinate.
        wgsY = data["y"]
        # Print output to python window in ArcMap.
        print "X:" + str(wgsX) + " Y:" + str(wgsY)
        # Structure url string and pass X&Y parameters to string.
        url = 'https://pol.pictometry.com/en-us/app/default.php?lat={0}&lon={1}&v=p&o=s&type=ob&level=n'.format(str(wgsY),str(wgsX))
        # ArcMap and python add-ins are sensitive to threading.
        # Therefore to open a separate process it needs to be opened
        # in it's own thread so it does not interfere with ArcMap.
        # The code below will open the url in a new tab in a separate thread.
        threading.Thread(target=webbrowser.open, args=(url,0)).start()

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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