Reader for the MaxMind DB format
npx @tessl/cli install tessl/pypi-maxminddb@2.8.0A high-performance Python reader for MaxMind DB files, which are binary database files that store data indexed by IP address subnets (IPv4 or IPv6). The library includes both a pure Python implementation and an optional C extension for enhanced performance, supporting multiple reading modes including memory mapping, file-based access, and in-memory loading.
pip install maxminddbimport maxminddbFor accessing specific components:
from maxminddb import open_database, Reader, InvalidDatabaseError
from maxminddb import MODE_AUTO, MODE_MMAP, MODE_FILE, MODE_MEMORY, MODE_FD, MODE_MMAP_EXTimport maxminddb
# Open a MaxMind DB file
with maxminddb.open_database('/path/to/GeoIP2-City.mmdb') as reader:
# Look up an IP address
response = reader.get('128.101.101.101')
print(response['country']['iso_code']) # Example: 'US'
# Get response with network prefix length
response, prefix_len = reader.get_with_prefix_len('128.101.101.101')
print(f"Network: {response}, Prefix: {prefix_len}")
# Access database metadata
metadata = reader.metadata()
print(f"Database type: {metadata.database_type}")
print(f"Build time: {metadata.build_epoch}")MaxMind DB uses a binary tree structure for efficient IP address lookups:
Opens MaxMind DB files with configurable access modes for different performance and memory usage characteristics.
def open_database(
database: str | int | os.PathLike | IO,
mode: int = MODE_AUTO
) -> Reader:
"""
Open a MaxMind DB database.
Parameters:
- database: Path to MaxMind DB file, or file descriptor for MODE_FD
- mode: Database access mode (see Mode Constants)
Returns:
Reader: Database reader instance
Raises:
ValueError: If unsupported mode specified
InvalidDatabaseError: If file is not a valid MaxMind DB
"""Core functionality for retrieving data associated with IP addresses from the database.
class Reader:
"""Reader for MaxMind DB files with IP lookup capabilities."""
closed: bool # Indicates whether the database has been closed
def __init__(
self,
database: str | int | os.PathLike | IO,
mode: int = MODE_AUTO
):
"""
Initialize MaxMind DB reader.
Parameters:
- database: Path to MaxMind DB file, or file descriptor for MODE_FD
- mode: Database access mode
"""
def get(self, ip_address: str | IPv4Address | IPv6Address) -> Record | None:
"""
Return the record for the IP address.
Parameters:
- ip_address: IP address in string notation or ipaddress object
Returns:
Record | None: Database record or None if not found
Raises:
TypeError: If ip_address is not string or ipaddress object
ValueError: If IPv6 address used with IPv4-only database
"""
def get_with_prefix_len(
self,
ip_address: str | IPv4Address | IPv6Address
) -> tuple[Record | None, int]:
"""
Return record with associated network prefix length.
Parameters:
- ip_address: IP address in string notation or ipaddress object
Returns:
tuple[Record | None, int]: (record, prefix_length)
"""
def metadata(self) -> Metadata:
"""
Return database metadata.
Returns:
Metadata: Database metadata object
"""
def close(self) -> None:
"""Close database and release resources."""
def __enter__(self) -> Reader:
"""Context manager entry."""
def __exit__(self, *args) -> None:
"""Context manager exit with automatic cleanup."""
def __iter__(self) -> Iterator[tuple[ipaddress.IPv4Network | ipaddress.IPv6Network, Record]]:
"""
Iterate over all database records.
Yields:
tuple: (network, record) pairs for all entries
"""Access to comprehensive database metadata including format version, build information, and structural details.
class Metadata:
"""Container for MaxMind DB metadata information."""
def __init__(self, **kwargs):
"""Create Metadata object from database metadata."""
# Core metadata attributes
binary_format_major_version: int # Major version of binary format
binary_format_minor_version: int # Minor version of binary format
build_epoch: int # Unix timestamp of database build
database_type: str # Database type identifier (e.g., "GeoIP2-City")
description: dict[str, str] # Locale-to-description mapping
ip_version: int # IP version (4 or 6)
languages: list[str] # Supported locale codes
node_count: int # Number of nodes in search tree
record_size: int # Bit size of tree records
@property
def node_byte_size(self) -> int:
"""Size of a node in bytes."""
@property
def search_tree_size(self) -> int:
"""Size of the search tree in bytes."""Database access mode constants that control how the database file is read and cached.
# Database access modes
MODE_AUTO: int # Auto-select best available mode (default)
MODE_MMAP_EXT: int # Memory mapping with C extension (fastest)
MODE_MMAP: int # Memory mapping, pure Python
MODE_FILE: int # Standard file I/O, pure Python
MODE_MEMORY: int # Load entire database into memory, pure Python
MODE_FD: int # Read from file descriptor, pure PythonError handling for database-related operations and invalid data conditions.
class InvalidDatabaseError(RuntimeError):
"""
Exception raised when invalid or corrupt database data is encountered.
This includes cases where:
- File is not a valid MaxMind DB format
- Database metadata is corrupt or unreadable
- Search tree contains invalid node data
"""# Type aliases for database records
from typing import Union, AnyStr
Primitive = Union[AnyStr, bool, float, int]
Record = Union[Primitive, "RecordList", "RecordDict"]
class RecordList(list[Record]):
"""List container for database record arrays."""
class RecordDict(dict[str, Record]):
"""Dictionary container for database record objects."""import maxminddb
# Memory mapping (fastest for repeated lookups)
reader = maxminddb.open_database('/path/to/db.mmdb', maxminddb.MODE_MMAP)
# File I/O (lowest memory usage)
reader = maxminddb.open_database('/path/to/db.mmdb', maxminddb.MODE_FILE)
# Load into memory (fastest for small databases)
reader = maxminddb.open_database('/path/to/db.mmdb', maxminddb.MODE_MEMORY)
# Using file descriptor
with open('/path/to/db.mmdb', 'rb') as f:
reader = maxminddb.open_database(f, maxminddb.MODE_FD)import maxminddb
with maxminddb.open_database('/path/to/db.mmdb') as reader:
# Iterate over all network/record pairs
for network, record in reader:
print(f"Network: {network}, Data: {record}")
# Process each record as neededimport maxminddb
from maxminddb import InvalidDatabaseError
try:
reader = maxminddb.open_database('/path/to/db.mmdb')
result = reader.get('192.168.1.1')
except InvalidDatabaseError as e:
print(f"Database error: {e}")
except ValueError as e:
print(f"Invalid input: {e}")
except FileNotFoundError:
print("Database file not found")
finally:
if 'reader' in locals():
reader.close()import maxminddb
from datetime import datetime
with maxminddb.open_database('/path/to/db.mmdb') as reader:
metadata = reader.metadata()
print(f"Database: {metadata.database_type}")
print(f"IP Version: IPv{metadata.ip_version}")
print(f"Languages: {', '.join(metadata.languages)}")
print(f"Build Date: {datetime.fromtimestamp(metadata.build_epoch)}")
print(f"Node Count: {metadata.node_count:,}")
print(f"Record Size: {metadata.record_size} bits")
# Access description in different languages
for locale, desc in metadata.description.items():
print(f"Description ({locale}): {desc}")