我想知道为什么以下不起作用。
from twisted internet import defer, reactor
from twisted.python.failure import Failure
import twisted.names.client
def do_lookup(do_lookup):
d = twisted.names.client.getHostByName(domain)
d.addBoth(lookup_done)
def lookup_done(result):
print 'result:', result
reactor.stop()
domain = 'twistedmatrix.com'
reactor.callLater(0, do_lookup, domain)
reactor.run()
结果:
result: [Failure instance: Traceback
(failure with no frames): <class
'twisted.names.error.ResolverError'>:
Stuck at response without answers or
delegation ]
答案 0 :(得分:5)
在撰写本文时,这在Windows上失败,因为它使用了无效的路径来存放Windows主机文件(在twisted.names.client.createResolver中。它使用'c:\ windows \ hosts'。这对Windows版本98来说很好和我(参考here),但失败的版本与XP一样“现代”。
今天,应该使用类似的东西:
hosts = os.path.join(
os.environ.get('systemroot','C:\\Windows'),
r'system32\drivers\etc\hosts'
)
我认为这只能部分地解决问题(或者这可能是一个红色的鲱鱼)。
这仅适用于此hosts文件中实际指定的名称。它可能需要做的是DNS服务器的某种注册表查询,然后查询实际的DNS名称查找。
This 配方看起来很有希望获得实际的DNS服务器。
答案 1 :(得分:3)
将您的示例更正为以下内容,以使其在语法上有效:
from twisted.internet import reactor
import twisted.names.client
def do_lookup(domain):
d = twisted.names.client.getHostByName(domain)
d.addBoth(lookup_done)
def lookup_done(result):
print 'result:', result
reactor.stop()
domain = 'twistedmatrix.com'
reactor.callLater(0, do_lookup, domain)
reactor.run()
我明白了:
$ python so-example.py
result: 66.35.39.65
所以,回答你的问题:你的本地DNS环境坏了,而不是twisted.names。或者也许有一个错误。你需要进一步追踪它。
答案 2 :(得分:1)
我做了一些挖掘,为什么显式client.createResolver(servers)
无法在我们的企业Windows机器上运行。在guts of Twisted的createResolver
是一个依赖于os的分支:
def createResolver(servers=None, resolvconf=None, hosts=None):
...
from twisted.names import resolve, cache, root, hosts as hostsModule
if platform.getType() == 'posix':
if resolvconf is None:
resolvconf = '/etc/resolv.conf'
if hosts is None:
hosts = '/etc/hosts'
theResolver = Resolver(resolvconf, servers)
hostResolver = hostsModule.Resolver(hosts)
else:
if hosts is None:
hosts = r'c:\windows\hosts'
from twisted.internet import reactor
bootstrap = _ThreadedResolverImpl(reactor)
hostResolver = hostsModule.Resolver(hosts)
theResolver = root.bootstrap(bootstrap)
L = [hostResolver, cache.CacheResolver(), theResolver]
return resolve.ResolverChain(L)
Windows的第一个警告标志是未使用参数servers
,因此将忽略自定义DNS服务器。接下来是_ThreadedResolverImpl(),它使用特定于平台的代码,在被添加到解析器链之前被包装在root.bootstrap()
中。
root.bootstrap的目的是使用平台解析器使用同步Windows平台解析器(工作 - 并返回IP)查找a.root-servers.net,b.root-servers.net等,然后对 root 服务器进行直接DNS查询。然后,我们的公司防火墙会阻止向根服务器发出的UDP数据包 - 我在Wireshark中看到它们。
names.client.getHostByName()使用的默认getResolver()调用直接调用createResolver()
,这可能会再次导致由正在运行的DNS设置引导的这个损坏的设置。对于大多数环境,我认为将Resolver(带有根服务器或显式服务器)与_ThreadedResolverImpl
一起添加到ResolverChain中作为后备工作 - 除了平台解析器是一个不同的接口。
以下是异步检测本地DNS服务器的示例(通过解析ipconfig
的输出),然后安装自定义解析程序以使用它们。
import sys
from twisted.python import log
from twisted.names import root, hosts, resolve, cache, client
from twisted.python.runtime import platform
from twisted.internet import reactor
from twisted.internet import utils
import re
def parseIpconfigDNSServers(output):
servers = []
found = False
for line in output.split('\n'):
if 'DNS Servers . . . . . . . . . . . :' in line or (found and not '. . . .' in line):
servers.append(line[38:].strip())
found = True
else:
found = False
log.msg( 'Windows: Detected DNS servers %s' % (str(servers)))
return servers
if platform.getType() != 'posix':
d = utils.getProcessOutput(os.path.join(os.environ['WINDIR'], 'system32', 'ipconfig.exe'), ["/all"])
d.addCallback(parseIpconfigDNSServers)
d.addCallback(lambda r: client.Resolver(servers=[(h, 53) for h in r]))
d.addErrback(log.msg)
theResolver = root.DeferredResolver(d)
client.theResolver = resolve.ResolverChain([cache.CacheResolver(), theResolver])
if __name__ == '__main__':
log.startLogging(sys.stdout)
def do_lookup(domain):
d = client.getHostByName(domain)
d.addBoth(log.msg)
from twisted.internet import reactor
reactor.callLater(0, do_lookup, 'example.com')
reactor.run()
我已将其整理并在此处发布https://gist.github.com/shuckc/af7490e1c4a2652ca740