Created
January 26, 2025 16:49
-
-
Save simonw/178ea93ac035293744bde97270d6a7a0 to your computer and use it in GitHub Desktop.
Geocode using the API bulit into macOS CoreLocation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# /// script | |
# requires-python = ">=3.12" | |
# dependencies = [ | |
# "pyobjc-core", | |
# "pyobjc-framework-CoreLocation", | |
# "click" | |
# ] | |
# /// | |
"""Basic geocoding using CoreLocation on macOS.""" | |
import click | |
import objc | |
from CoreLocation import CLGeocoder | |
from Foundation import NSRunLoop, NSDate | |
def forward_geocode(address: str) -> list[dict]: | |
with objc.autorelease_pool(): | |
geocoder = CLGeocoder.alloc().init() | |
results = {"placemarks": [], "error": None} | |
completed = False | |
def completion(placemarks, error): | |
nonlocal completed | |
if error: | |
results["error"] = error.localizedDescription() | |
elif placemarks: | |
results["placemarks"] = placemarks | |
completed = True | |
geocoder.geocodeAddressString_completionHandler_(address, completion) | |
while not completed: | |
NSRunLoop.currentRunLoop().runMode_beforeDate_( | |
"NSDefaultRunLoopMode", | |
NSDate.dateWithTimeIntervalSinceNow_(0.1) | |
) | |
if results["error"]: | |
raise Exception(f"Geocoding error: {results['error']}") | |
return [{ | |
"latitude": pm.location().coordinate().latitude, | |
"longitude": pm.location().coordinate().longitude, | |
"name": pm.name(), | |
"locality": pm.locality(), | |
"country": pm.country() | |
} for pm in results["placemarks"]] | |
@click.command() | |
@click.argument('address') | |
def main(address): | |
try: | |
locations = forward_geocode(address) | |
for loc in locations: | |
click.echo("\nLocation found:") | |
for key, value in loc.items(): | |
if value: | |
click.echo(f"{key}: {value}") | |
except Exception as e: | |
click.echo(f"Error: {e}", err=True) | |
raise click.Abort() | |
if __name__ == "__main__": | |
main() |
Run like this:
uv run https://gist.githubusercontent.com/simonw/178ea93ac035293744bde97270d6a7a0/raw/88c817e4103034579ec7523d8591bf60aa11fa67/geocode.py \
'500 Grove St, San Francisco'
Output:
Location found:
latitude: 37.777717
longitude: -122.42504
name: 500 Grove St
locality: San Francisco
country: United States
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Inspired by: https://gist.github.com/RhetTbull/db70c113efd03029c6ff619f4699ce34
Code by Claude: https://gist.github.com/simonw/fed886265bc32af81efa8e7973fea621