{"id":10074,"library":"py3dns","title":"Py3DNS - Python 3 DNS library","description":"Py3DNS is a Python 3 library for making DNS queries and parsing responses. It provides a flexible API for various record types (A, AAAA, MX, NS, SOA, etc.) and is a port of the older `pydns` library, specifically adapted for Python 3. The current version is 4.0.2, with updates primarily focusing on Python compatibility, bug fixes, and feature enhancements like `asyncio` support.","status":"active","version":"4.0.2","language":"en","source_language":"en","source_url":"https://github.com/dohliam/py3dns","tags":["dns","networking","asyncio","python3"],"install":[{"cmd":"pip install py3dns","lang":"bash","label":"Install Py3DNS"}],"dependencies":[],"imports":[{"note":"The primary API is exposed directly under the 'DNS' module namespace after 'import DNS'.","wrong":"from py3dns import DNS","symbol":"DNS","correct":"import DNS"}],"quickstart":{"code":"import DNS\nimport os\n\n# Configure name servers, typically from system settings\n# For testing, you can explicitly set them or rely on system discovery\n# Example using Google's DNS for demonstration if system discovery fails or for specific testing\n# DNS.defaults['server'] = ['8.8.8.8', '8.8.4.4']\n\n# Discover name servers from /etc/resolv.conf or common system locations\nDNS.DiscoverNameServers()\n\n# Ensure name servers were found or set\nif not DNS.defaults.get('server'):\n    print(\"Warning: No DNS name servers discovered. Queries might fail.\")\n    print(\"Attempting to use public DNS servers as fallback.\")\n    DNS.defaults['server'] = ['8.8.8.8', '8.8.4.4'] # Fallback to Google DNS\n\n# Make an A record query for google.com\ntry:\n    req = DNS.Request(name='google.com', qtype='A')\n    response = req.req()\n\n    print(f\"DNS Query for google.com (A records):\\n\")\n    if response.answers:\n        for answer in response.answers:\n            print(f\"  Name: {answer.name}, Type: {answer.qtype}, Data: {answer.data}, TTL: {answer.ttl}\")\n    else:\n        print(\"  No A records found for google.com.\")\n\n    # Example: MX record query\n    req_mx = DNS.Request(name='example.com', qtype='MX')\n    response_mx = req_mx.req()\n    print(f\"\\nDNS Query for example.com (MX records):\\n\")\n    if response_mx.answers:\n        for answer in response_mx.answers:\n            print(f\"  Name: {answer.name}, Type: {answer.qtype}, Priority: {answer.data[0]}, Exchange: {answer.data[1]}\")\n    else:\n        print(\"  No MX records found for example.com.\")\n\nexcept DNS.DNSError as e:\n    print(f\"DNS Error: {e}\")\nexcept Exception as e:\n    print(f\"An unexpected error occurred: {e}\")","lang":"python","description":"This quickstart demonstrates how to perform basic A and MX record DNS queries using Py3DNS. It includes name server discovery and a fallback to public DNS if discovery fails, making the example robust for various environments."},"warnings":[{"fix":"Ensure `py3dns` is installed (`pip install py3dns`). Review your existing `pydns` code and adjust for Python 3 syntax and module differences. Test thoroughly.","message":"Direct migration from Python 2's 'pydns' to 'py3dns' is not straightforward, as 'py3dns' is a separate project with Python 3 specific adjustments. While the API is largely compatible, code will require Python 3 syntax and 'py3dns' installation.","severity":"breaking","affected_versions":"All versions of py3dns (when migrating from pydns)"},{"fix":"Call `DNS.DiscoverNameServers()` or `DNS.ParseResolvConf()` before making any `DNS.Request` calls to ensure name servers are properly set up. Alternatively, set `DNS.defaults['server'] = ['your_dns_server_ip']`.","message":"DNS queries will fail with a 'No name servers specified' error if name servers are not explicitly configured or automatically discovered before making requests.","severity":"gotcha","affected_versions":"All versions"},{"fix":"For concurrent or non-blocking operations, consider using Py3DNS's `asyncio` integration (e.g., `DNS.async_req`) introduced in version 4.0.0, or manage concurrency using Python's `threading` or `multiprocessing` modules.","message":"Synchronous DNS requests (e.g., `DNS.Request.req()`) are blocking and can lead to performance bottlenecks or frozen applications in concurrent or I/O-bound environments.","severity":"gotcha","affected_versions":"All versions prior to 4.0.0, and synchronous usage in 4.x+"}],"env_vars":null,"last_verified":"2026-04-17T00:00:00.000Z","next_check":"2026-07-16T00:00:00.000Z","problems":[{"fix":"Verify that `py3dns` is installed in your active environment by running `pip install py3dns`. Ensure your Python interpreter matches the environment where `py3dns` is installed.","cause":"This error typically occurs if `py3dns` is not installed, or if an attempt was made to install the Python 2-only `pydns` package instead.","error":"ModuleNotFoundError: No module named 'DNS'"},{"fix":"Before making any `DNS.Request`, ensure name servers are set up by calling `DNS.DiscoverNameServers()`, `DNS.ParseResolvConf()`, or by manually setting `DNS.defaults['server'] = ['IP_ADDRESS_1', 'IP_ADDRESS_2']`.","cause":"The library could not find or was not explicitly provided with any DNS name server addresses to send queries to, often because `DNS.DiscoverNameServers()` was not called or failed.","error":"DNSError: No name servers specified"},{"fix":"Increase the timeout value by setting `DNS.defaults['timeout'] = X` (where `X` is the timeout in seconds) before making the request. Also, check your network connectivity and the availability of your configured DNS servers.","cause":"A DNS query took longer than the default or configured timeout period, often due to network issues, an unresponsive DNS server, or a very slow connection.","error":"socket.timeout: timed out"}]}