DNSPython 异步解析超时但同步解析不会
DNSPython asynchronous resolve times out but synchronous resolve doesn't
我在 Python 3.9.7 x64、dnspython 2.1.0 和 Windows 10 21H1 上进行了测试。
问题很简单:
dns.resolver.Resolver()
正常工作但 dns.asyncresolver.Resolver()
不正常,它们应该具有相同的 API,但是前者确实 return 结果,后者总是出。
示例:
In [55]: import dns
...: sequential_resolver = dns.resolver.Resolver()
...: sequential_resolver.nameservers = ['8.8.8.8']
In [56]: ans = sequential_resolver.resolve('www.google.com')
In [57]: ans[0].address
Out[57]: '162.125.18.129'
In [58]: from dns.asyncresolver import Resolver
In [59]: resolver = Resolver()
In [60]: resolver.nameservers = ['8.8.8.8']
In [61]: asyncio.run(resolver.resolve('www.google.com'))
---------------------------------------------------------------------------
Timeout Traceback (most recent call last)
<ipython-input-61-4971055f7c5e> in <module>
----> 1 asyncio.run(resolver.resolve('www.google.com'))
C:\Program Files\Python39\lib\asyncio\runners.py in run(main, debug)
42 if debug is not None:
43 loop.set_debug(debug)
---> 44 return loop.run_until_complete(main)
45 finally:
46 try:
C:\Program Files\Python39\lib\asyncio\base_events.py in run_until_complete(self, future)
640 raise RuntimeError('Event loop stopped before Future completed.')
641
--> 642 return future.result()
643
644 def stop(self):
C:\Program Files\Python39\lib\site-packages\dns\asyncresolver.py in resolve(self, qname, rdtype, rdclass, tcp, source, raise_on_no_answer, source_port, lifetime, search, backend)
72 if backoff:
73 await backend.sleep(backoff)
---> 74 timeout = self._compute_timeout(start, lifetime)
75 try:
76 if dns.inet.is_address(nameserver):
C:\Program Files\Python39\lib\site-packages\dns\resolver.py in _compute_timeout(self, start, lifetime)
995 now = start
996 if duration >= lifetime:
--> 997 raise Timeout(timeout=duration)
998 return min(lifetime - duration, self.timeout)
999
Timeout: The DNS operation timed out after 5.407369613647461 seconds
我可以向你保证这个问题不是由我的物理宽带连接引起的:
PS C:\Windows\System32> ping 8.8.8.8
Pinging 8.8.8.8 with 32 bytes of data:
Reply from 8.8.8.8: bytes=32 time=66ms TTL=48
Reply from 8.8.8.8: bytes=32 time=66ms TTL=48
Reply from 8.8.8.8: bytes=32 time=66ms TTL=48
Reply from 8.8.8.8: bytes=32 time=67ms TTL=48
Ping statistics for 8.8.8.8:
Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
Minimum = 66ms, Maximum = 67ms, Average = 66ms
如何解决?
它 looks like there's a bug in dnspython, but the fix doesn't seem 尚未在 PyPi 上发布。
我能建议的最好的办法是安装来自 Github 的版本:
pip install -U https://github.com/rthalley/dnspython/archive/master.zip
有了它,您的代码就可以工作了。
我在 Python 3.9.7 x64、dnspython 2.1.0 和 Windows 10 21H1 上进行了测试。
问题很简单:
dns.resolver.Resolver()
正常工作但 dns.asyncresolver.Resolver()
不正常,它们应该具有相同的 API,但是前者确实 return 结果,后者总是出。
示例:
In [55]: import dns
...: sequential_resolver = dns.resolver.Resolver()
...: sequential_resolver.nameservers = ['8.8.8.8']
In [56]: ans = sequential_resolver.resolve('www.google.com')
In [57]: ans[0].address
Out[57]: '162.125.18.129'
In [58]: from dns.asyncresolver import Resolver
In [59]: resolver = Resolver()
In [60]: resolver.nameservers = ['8.8.8.8']
In [61]: asyncio.run(resolver.resolve('www.google.com'))
---------------------------------------------------------------------------
Timeout Traceback (most recent call last)
<ipython-input-61-4971055f7c5e> in <module>
----> 1 asyncio.run(resolver.resolve('www.google.com'))
C:\Program Files\Python39\lib\asyncio\runners.py in run(main, debug)
42 if debug is not None:
43 loop.set_debug(debug)
---> 44 return loop.run_until_complete(main)
45 finally:
46 try:
C:\Program Files\Python39\lib\asyncio\base_events.py in run_until_complete(self, future)
640 raise RuntimeError('Event loop stopped before Future completed.')
641
--> 642 return future.result()
643
644 def stop(self):
C:\Program Files\Python39\lib\site-packages\dns\asyncresolver.py in resolve(self, qname, rdtype, rdclass, tcp, source, raise_on_no_answer, source_port, lifetime, search, backend)
72 if backoff:
73 await backend.sleep(backoff)
---> 74 timeout = self._compute_timeout(start, lifetime)
75 try:
76 if dns.inet.is_address(nameserver):
C:\Program Files\Python39\lib\site-packages\dns\resolver.py in _compute_timeout(self, start, lifetime)
995 now = start
996 if duration >= lifetime:
--> 997 raise Timeout(timeout=duration)
998 return min(lifetime - duration, self.timeout)
999
Timeout: The DNS operation timed out after 5.407369613647461 seconds
我可以向你保证这个问题不是由我的物理宽带连接引起的:
PS C:\Windows\System32> ping 8.8.8.8
Pinging 8.8.8.8 with 32 bytes of data:
Reply from 8.8.8.8: bytes=32 time=66ms TTL=48
Reply from 8.8.8.8: bytes=32 time=66ms TTL=48
Reply from 8.8.8.8: bytes=32 time=66ms TTL=48
Reply from 8.8.8.8: bytes=32 time=67ms TTL=48
Ping statistics for 8.8.8.8:
Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
Minimum = 66ms, Maximum = 67ms, Average = 66ms
如何解决?
它 looks like there's a bug in dnspython, but the fix doesn't seem 尚未在 PyPi 上发布。
我能建议的最好的办法是安装来自 Github 的版本:
pip install -U https://github.com/rthalley/dnspython/archive/master.zip
有了它,您的代码就可以工作了。