#!/usr/bin/env python # coding: utf-8 # In[13]: get_ipython().system('touch test.html') # In[30]: import webbrowser webbrowser.get('Safari').open('test.html') # Call LSCopyDefaultApplicationURLForURL to discover the location of the application associated with a given url. # # Use ctypes to call apple APIs. # In[2]: import ctypes from ctypes import c_void_p, Structure, POINTER kCFStringEncodingUTF8 = 0x08000100 CoreFoundation = ctypes.cdll.LoadLibrary(ctypes.util.find_library('CoreFoundation')) LaunchServices = ctypes.cdll.LoadLibrary(ctypes.util.find_library('LaunchServices')) # create CFURL from bytes CFURLCreateWithBytes = CoreFoundation.CFURLCreateWithBytes CFURLCreateWithBytes.restype = c_void_p CFURLCreateWithBytes.argtypes = [c_void_p, ctypes.c_char_p, ctypes.c_int, ctypes.c_uint32, c_void_p] # for debugging CreateWithBytes CFURLGetBytes = CoreFoundation.CFURLGetBytes CFURLGetBytes.restype = ctypes.c_int CFURLGetBytes.argtypes = [c_void_p, ctypes.c_char_p, ctypes.c_int] # get App associated with CFURL LSCopyDefaultApplicationURLForURL = LaunchServices.LSCopyDefaultApplicationURLForURL LSCopyDefaultApplicationURLForURL.restype = c_void_p LSCopyDefaultApplicationURLForURL.argtypes = [c_void_p, c_void_p, c_void_p] # In[39]: def app_for_url(url): """Returns file:// url for the app associated with a url""" cf_url = CFURLCreateWithBytes( None, url.encode('utf8'), len(url), kCFStringEncodingUTF8, None, ) cf_app = LSCopyDefaultApplicationURLForURL(cf_url, None, None) if cf_app is None: raise ValueError("No app found for %s" % url) buf = (ctypes.c_char * 1024)() CFURLGetBytes(cf_app, buf, len(buf)) return buf.value.decode('utf8') # In[40]: app_for_url("http://google.com") # Raises if there's no application found # In[41]: import os app_for_url("file://" + os.path.abspath("mac-detect-browser.ipynb")) # In[42]: import os app_for_url("file://" + os.path.abspath("untitled.txt")) # webbrowser doesn't know how to handle absolute paths: # In[44]: webbrowser.get("/Applications/Safari.app") # So we pick out the base name of the .app and hope that works: # In[45]: from urllib.parse import unquote def app_name_for_url(url): """Return the name of an app associated with a url""" app = app_for_url(url) path = app.split('://', 1)[1] basename = path.rstrip('/') name, dotapp = os.path.splitext(os.path.basename(path.rstrip('/'))) return unquote(name) # In[46]: app_name_for_url('http://google.com') # In[47]: browser = webbrowser.get(app_name_for_url('http://jupyter.org')) browser.open("file://" + os.path.abspath("test.html"))