types-geoip2
types-geoip2 provides PEP 561 compliant typing stubs for the geoip2 library. It enables static type checkers like mypy, PyCharm, and pytype to provide robust type checking and autocompletion for code using the geoip2 package. These stubs are maintained as part of the python/typeshed project on GitHub, with new versions automatically released to PyPI frequently (up to once a day) to reflect updates and improvements in typeshed.
Warnings
- breaking The `geoip2` package itself started including type annotations from version `4.0.2` onwards. If you are using `geoip2>=4.0.2`, installing `types-geoip2` is unnecessary and may lead to conflicts or outdated type information, as the runtime package's own annotations will often be more accurate.
- gotcha Typeshed stub packages (like `types-geoip2`) are released independently from the runtime library. While their version numbers often align with the runtime package they stub (e.g., `types-foo==1.2.0.YYYYMMDD` for `foo==1.2.*`), internal changes within typeshed's stubs can introduce new type-checking errors even if your runtime `geoip2` package version hasn't changed.
- gotcha In Python's module resolution order for typing, stub files (`.pyi`) from installed stub packages generally take precedence over inline type annotations (`.py`) in the actual library. This means if `types-geoip2` is installed alongside a `geoip2` version that has its own inline types (like `geoip2>=4.0.2`), the `types-geoip2` stubs might be used, potentially overriding newer or more accurate inline types from `geoip2`.
- gotcha When working with `geoip2` models, MaxMind strongly advises against using values from `names` properties (e.g., `response.city.names['en']`) as keys in databases or dictionaries. These human-readable names are subject to change between releases, potentially leading to broken logic.
Install
-
pip install types-geoip2
Imports
- Client
from geoip2.webservice import Client
- Reader
from geoip2.database import Reader
- City
from geoip2.models import City
Quickstart
import geoip2.database
import os
# Ensure you have a GeoLite2-City.mmdb file available for database lookups.
# Download from: https://dev.maxmind.com/geoip/downloads/maxmind-databases/
# For this example, we assume it's in the current directory or specified path.
# Replace with a real path if needed.
DB_PATH = os.environ.get('GEOLITE2_CITY_DB_PATH', 'GeoLite2-City.mmdb')
# If geoip2.database.Reader is initialized without the stub, type checkers might not know its methods.
# With types-geoip2 installed, mypy (or other type checkers) will correctly infer types.
reader: geoip2.database.Reader
try:
reader = geoip2.database.Reader(DB_PATH)
except geoip2.errors.AddressNotFoundError:
print(f"Database file not found at {DB_PATH}. Please provide a valid path or download the database.")
exit(1)
except Exception as e:
print(f"An error occurred initializing the database reader: {e}")
exit(1)
# Example IP address
ip_address = '8.8.8.8' # Google Public DNS
try:
response = reader.city(ip_address)
print(f"IP: {ip_address}")
print(f"Country Name: {response.country.name}")
print(f"City Name: {response.city.name}")
print(f"Latitude: {response.location.latitude}")
print(f"Longitude: {response.location.longitude}")
# Type checker will correctly identify `response` as geoip2.models.City
# and `response.country` as geoip2.records.Country
reveal_type(response) # For mypy to show the inferred type
except geoip2.errors.AddressNotFoundError:
print(f"IP address {ip_address} not found in the database.")
except Exception as e:
print(f"An error occurred during lookup: {e}")
finally:
reader.close()
# To run type checking, save this as `example.py` and run `mypy example.py`