Python interface for c-ares asynchronous DNS library
npx @tessl/cli install tessl/pypi-pycares@4.10.00
# pycares
1
2
A 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.
3
4
## Package Information
5
6
- **Package Name**: pycares
7
- **Language**: Python
8
- **Installation**: `pip install pycares`
9
10
## Core Imports
11
12
```python
13
import pycares
14
```
15
16
For error handling:
17
18
```python
19
import pycares.errno
20
```
21
22
For utilities:
23
24
```python
25
from pycares import ascii_bytes, maybe_str, parse_name
26
```
27
28
## Basic Usage
29
30
```python
31
import pycares
32
import select
33
34
def wait_channel(channel):
35
"""Helper function to process channel events until completion."""
36
while True:
37
read_fds, write_fds = channel.getsock()
38
if not read_fds and not write_fds:
39
break
40
timeout = channel.timeout()
41
if not timeout:
42
channel.process_fd(pycares.ARES_SOCKET_BAD, pycares.ARES_SOCKET_BAD)
43
continue
44
rlist, wlist, xlist = select.select(read_fds, write_fds, [], timeout)
45
for fd in rlist:
46
channel.process_fd(fd, pycares.ARES_SOCKET_BAD)
47
for fd in wlist:
48
channel.process_fd(pycares.ARES_SOCKET_BAD, fd)
49
50
def query_callback(result, error):
51
"""Callback function for DNS queries."""
52
if error is not None:
53
print(f'Error: ({error}) {pycares.errno.strerror(error)}')
54
else:
55
print(f'Result: {result}')
56
57
# Create a DNS resolution channel
58
channel = pycares.Channel()
59
60
# Perform a simple A record query
61
channel.query('google.com', pycares.QUERY_TYPE_A, query_callback)
62
63
# Process the query until completion
64
wait_channel(channel)
65
66
# Clean up
67
channel.close()
68
```
69
70
## Architecture
71
72
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.
73
74
Key components:
75
- **Channel**: The main DNS resolution engine that manages queries, servers, and I/O
76
- **Result classes**: Structured objects containing parsed DNS response data for each record type
77
- **Callback system**: Asynchronous completion notification via user-provided callback functions
78
- **Event loop integration**: Socket-based I/O monitoring for integration with select, asyncio, and other event systems
79
80
## Capabilities
81
82
### Utility Functions
83
84
String encoding and domain name processing utilities for handling international domain names and proper ASCII encoding.
85
86
```python { .api }
87
def ascii_bytes(data): ...
88
def maybe_str(data): ...
89
def parse_name(name): ...
90
```
91
92
[Utilities](./utilities.md)
93
94
### DNS Channel Management
95
96
Core functionality for creating and configuring DNS resolution channels, including server configuration, timeout settings, and I/O event processing.
97
98
```python { .api }
99
class Channel:
100
def __init__(
101
self,
102
flags=None,
103
timeout=None,
104
tries=None,
105
ndots=None,
106
tcp_port=None,
107
udp_port=None,
108
servers=None,
109
domains=None,
110
lookups=None,
111
sock_state_cb=None,
112
socket_send_buffer_size=None,
113
socket_receive_buffer_size=None,
114
rotate=False,
115
local_ip=None,
116
local_dev=None,
117
resolvconf_path=None,
118
event_thread=False
119
): ...
120
121
def getsock(self): ...
122
def timeout(self, t=None): ...
123
def process_fd(self, read_fd, write_fd): ...
124
def close(self): ...
125
```
126
127
[Channel Management](./channel-management.md)
128
129
### DNS Queries
130
131
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.
132
133
```python { .api }
134
def query(self, name, query_type, callback, query_class=None): ...
135
def search(self, name, query_type, callback, query_class=None): ...
136
```
137
138
[DNS Queries](./dns-queries.md)
139
140
### Host Resolution
141
142
Traditional host resolution functions similar to standard library socket functions but with asynchronous callback-based operation.
143
144
```python { .api }
145
def gethostbyname(self, name, family, callback): ...
146
def gethostbyaddr(self, addr, callback): ...
147
def getaddrinfo(self, host, port, callback, family=0, type=0, proto=0, flags=0): ...
148
def getnameinfo(self, address, flags, callback): ...
149
```
150
151
[Host Resolution](./host-resolution.md)
152
153
### Error Handling and Constants
154
155
Comprehensive error code definitions and utility functions for handling DNS resolution errors and failures.
156
157
```python { .api }
158
# Error constants available in pycares.errno
159
ARES_SUCCESS: int
160
ARES_ENOTFOUND: int
161
ARES_ETIMEOUT: int
162
# ... additional error codes
163
164
def strerror(code: int) -> str: ...
165
```
166
167
[Error Handling](./error-handling.md)
168
169
## Command Line Interface
170
171
pycares includes a command-line interface for performing DNS queries similar to the `dig` command:
172
173
```bash
174
# Usage: python -m pycares [query_type] hostname
175
176
# Perform A record lookup (default)
177
python -m pycares google.com
178
179
# Perform specific record type lookup
180
python -m pycares mx google.com
181
python -m pycares txt google.com
182
python -m pycares aaaa google.com
183
python -m pycares ns google.com
184
```
185
186
The CLI outputs results in dig-like format with question and answer sections, including TTL values and properly formatted record data.
187
188
## Thread Safety
189
190
pycares supports thread-safe operation when the underlying c-ares library is compiled with thread safety. Check thread safety support:
191
192
```python { .api }
193
def ares_threadsafety() -> bool: ...
194
```
195
196
## Version Information
197
198
```python { .api }
199
__version__: str # Package version string
200
```
201
202
## Constants and Types
203
204
```python { .api }
205
# Type aliases
206
IP4 = tuple[str, int]
207
IP6 = tuple[str, int, int, int]
208
209
# Query types
210
QUERY_TYPE_A: int
211
QUERY_TYPE_AAAA: int
212
QUERY_TYPE_MX: int
213
QUERY_TYPE_TXT: int
214
QUERY_TYPE_SOA: int
215
QUERY_TYPE_SRV: int
216
QUERY_TYPE_NS: int
217
QUERY_TYPE_PTR: int
218
QUERY_TYPE_CNAME: int
219
QUERY_TYPE_CAA: int
220
QUERY_TYPE_NAPTR: int
221
QUERY_TYPE_ANY: int
222
223
# Channel flags
224
ARES_FLAG_USEVC: int
225
ARES_FLAG_PRIMARY: int
226
ARES_FLAG_IGNTC: int
227
ARES_FLAG_NORECURSE: int
228
ARES_FLAG_STAYOPEN: int
229
ARES_FLAG_NOSEARCH: int
230
ARES_FLAG_NOALIASES: int
231
ARES_FLAG_NOCHECKRESP: int
232
ARES_FLAG_EDNS: int
233
ARES_FLAG_NO_DFLT_SVR: int
234
235
# Name info flags
236
ARES_NI_NOFQDN: int
237
ARES_NI_NUMERICHOST: int
238
ARES_NI_NAMEREQD: int
239
ARES_NI_NUMERICSERV: int
240
ARES_NI_DGRAM: int
241
ARES_NI_TCP: int
242
ARES_NI_UDP: int
243
ARES_NI_SCTP: int
244
ARES_NI_DCCP: int
245
ARES_NI_NUMERICSCOPE: int
246
ARES_NI_LOOKUPHOST: int
247
ARES_NI_LOOKUPSERVICE: int
248
ARES_NI_IDN: int
249
ARES_NI_IDN_ALLOW_UNASSIGNED: int
250
ARES_NI_IDN_USE_STD3_ASCII_RULES: int
251
252
# Query classes
253
QUERY_CLASS_IN: int
254
QUERY_CLASS_CHAOS: int
255
QUERY_CLASS_HS: int
256
QUERY_CLASS_NONE: int
257
QUERY_CLASS_ANY: int
258
259
# Other constants
260
ARES_SOCKET_BAD: int
261
ARES_VERSION: str
262
```