Python interface for c-ares asynchronous DNS library
npx @tessl/cli install tessl/pypi-pycares@4.10.0A Python interface for c-ares, a C library that performs DNS requests and name resolutions asynchronously. pycares enables Python applications to perform non-blocking DNS queries including A, AAAA, MX, and other record types, making it ideal for high-performance networking applications that need to handle multiple concurrent DNS lookups without blocking execution.
pip install pycaresimport pycaresFor error handling:
import pycares.errnoFor utilities:
from pycares import ascii_bytes, maybe_str, parse_nameimport pycares
import select
def wait_channel(channel):
"""Helper function to process channel events until completion."""
while True:
read_fds, write_fds = channel.getsock()
if not read_fds and not write_fds:
break
timeout = channel.timeout()
if not timeout:
channel.process_fd(pycares.ARES_SOCKET_BAD, pycares.ARES_SOCKET_BAD)
continue
rlist, wlist, xlist = select.select(read_fds, write_fds, [], timeout)
for fd in rlist:
channel.process_fd(fd, pycares.ARES_SOCKET_BAD)
for fd in wlist:
channel.process_fd(pycares.ARES_SOCKET_BAD, fd)
def query_callback(result, error):
"""Callback function for DNS queries."""
if error is not None:
print(f'Error: ({error}) {pycares.errno.strerror(error)}')
else:
print(f'Result: {result}')
# Create a DNS resolution channel
channel = pycares.Channel()
# Perform a simple A record query
channel.query('google.com', pycares.QUERY_TYPE_A, query_callback)
# Process the query until completion
wait_channel(channel)
# Clean up
channel.close()pycares is built around the Channel class, which represents a DNS resolution context. The architecture supports both synchronous-style blocking operations (using helper functions like the wait_channel example above) and full asynchronous integration with event loops.
Key components:
String encoding and domain name processing utilities for handling international domain names and proper ASCII encoding.
def ascii_bytes(data): ...
def maybe_str(data): ...
def parse_name(name): ...Core functionality for creating and configuring DNS resolution channels, including server configuration, timeout settings, and I/O event processing.
class Channel:
def __init__(
self,
flags=None,
timeout=None,
tries=None,
ndots=None,
tcp_port=None,
udp_port=None,
servers=None,
domains=None,
lookups=None,
sock_state_cb=None,
socket_send_buffer_size=None,
socket_receive_buffer_size=None,
rotate=False,
local_ip=None,
local_dev=None,
resolvconf_path=None,
event_thread=False
): ...
def getsock(self): ...
def timeout(self, t=None): ...
def process_fd(self, read_fd, write_fd): ...
def close(self): ...DNS query operations for all major record types including A, AAAA, MX, TXT, SOA, SRV, and others. Supports both direct queries and search-based queries using configured search domains.
def query(self, name, query_type, callback, query_class=None): ...
def search(self, name, query_type, callback, query_class=None): ...Traditional host resolution functions similar to standard library socket functions but with asynchronous callback-based operation.
def gethostbyname(self, name, family, callback): ...
def gethostbyaddr(self, addr, callback): ...
def getaddrinfo(self, host, port, callback, family=0, type=0, proto=0, flags=0): ...
def getnameinfo(self, address, flags, callback): ...Comprehensive error code definitions and utility functions for handling DNS resolution errors and failures.
# Error constants available in pycares.errno
ARES_SUCCESS: int
ARES_ENOTFOUND: int
ARES_ETIMEOUT: int
# ... additional error codes
def strerror(code: int) -> str: ...pycares includes a command-line interface for performing DNS queries similar to the dig command:
# Usage: python -m pycares [query_type] hostname
# Perform A record lookup (default)
python -m pycares google.com
# Perform specific record type lookup
python -m pycares mx google.com
python -m pycares txt google.com
python -m pycares aaaa google.com
python -m pycares ns google.comThe CLI outputs results in dig-like format with question and answer sections, including TTL values and properly formatted record data.
pycares supports thread-safe operation when the underlying c-ares library is compiled with thread safety. Check thread safety support:
def ares_threadsafety() -> bool: ...__version__: str # Package version string# Type aliases
IP4 = tuple[str, int]
IP6 = tuple[str, int, int, int]
# Query types
QUERY_TYPE_A: int
QUERY_TYPE_AAAA: int
QUERY_TYPE_MX: int
QUERY_TYPE_TXT: int
QUERY_TYPE_SOA: int
QUERY_TYPE_SRV: int
QUERY_TYPE_NS: int
QUERY_TYPE_PTR: int
QUERY_TYPE_CNAME: int
QUERY_TYPE_CAA: int
QUERY_TYPE_NAPTR: int
QUERY_TYPE_ANY: int
# Channel flags
ARES_FLAG_USEVC: int
ARES_FLAG_PRIMARY: int
ARES_FLAG_IGNTC: int
ARES_FLAG_NORECURSE: int
ARES_FLAG_STAYOPEN: int
ARES_FLAG_NOSEARCH: int
ARES_FLAG_NOALIASES: int
ARES_FLAG_NOCHECKRESP: int
ARES_FLAG_EDNS: int
ARES_FLAG_NO_DFLT_SVR: int
# Name info flags
ARES_NI_NOFQDN: int
ARES_NI_NUMERICHOST: int
ARES_NI_NAMEREQD: int
ARES_NI_NUMERICSERV: int
ARES_NI_DGRAM: int
ARES_NI_TCP: int
ARES_NI_UDP: int
ARES_NI_SCTP: int
ARES_NI_DCCP: int
ARES_NI_NUMERICSCOPE: int
ARES_NI_LOOKUPHOST: int
ARES_NI_LOOKUPSERVICE: int
ARES_NI_IDN: int
ARES_NI_IDN_ALLOW_UNASSIGNED: int
ARES_NI_IDN_USE_STD3_ASCII_RULES: int
# Query classes
QUERY_CLASS_IN: int
QUERY_CLASS_CHAOS: int
QUERY_CLASS_HS: int
QUERY_CLASS_NONE: int
QUERY_CLASS_ANY: int
# Other constants
ARES_SOCKET_BAD: int
ARES_VERSION: str