Reputation: 391
I'm trying to use the dnspython library, and am a little confused by their example for querying MX records on this page: www.dnspython.org/examples.html:
import dns.resolver
answers = dns.resolver.query('dnspython.org', 'MX')
for rdata in answers:
print 'Host', rdata.exchange, 'has preference', rdata.preference
In the python CLI, a dir(answers) gives me:
['__class__', '__delattr__', '__delitem__', '__delslice__', '__dict__', '__doc__', '__getattr__', '__getattribute__', '__getitem__', '__getslice__', '__hash__', '__init__', '__iter__', '__len__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__str__', '__weakref__', 'expiration', 'qname', 'rdclass', 'rdtype', 'response', 'rrset']
Two things are confusing to me (which are related):
Upvotes: 2
Views: 6795
Reputation: 59633
I haven't looked at dns.resolver
as of yet - I just added it to the ever-growing list of things to check out. I would guess that rdata
refers to the resource record type specific data as described in Section 4.1.3 of RFC1035. The response of a DNS request contains three data sections in addition to the query and headers:
From the looks of it dns.resolver.query()
is returning the first section. In this case, each resource record in the answer section is going to have different attributes based on the record type. In this case, you asked for MX
records so the records should have exactly the attributes that you have - exchange
and preference
. These are described in Section 3.3.9 of RFC1035.
I suspect that dns.resolver
is overriding __getattr__
or something similar to perform the magic that you are seeing so you won't see the fields directly in a dir()
. Chances are that you are safe using the attributes as defined in RFC1035. I will definitely have to check this out tomorrow since I have need of a decent DNS subsystem for Python.
Thanks for mentioning this module and have fun with DNS. It is really pretty interesting stuff if you really dig into how it works. I still think that it is one of the earlier expressions of that ReSTful thing that is all the rage these days ;)
Upvotes: 1
Reputation: 882831
If you're on Python 2.6, the "proper" way to get the first item of any iterable (such as answers
here) is next(iter(answers))
; if you want to avoid an exception when answers
is an empty iterable, then next(iter(answers), somevalue)
will return somevalue
instead of raising StopIteration
. If you're on 2.5, then iter(answers).next()
, but you'll have to use it inside a try/except StopIteration:
statement if you need to deal with a possible empty iterable.
Upvotes: 0
Reputation: 46841
answers is an iterable as indicated by its "__iter__" method. Think of answers as a list of rdatas.
You can try doing this to get 1 rdata from answers:
answers.__iter__().next()
Upvotes: 1
Reputation: 56654
In the example code, answers
is an iterable object containing zero or more items, which are each assigned to rdata
in turn. To see the properties of the individual responses, try:
dir(answers[0])
Upvotes: 1