<p>我的第一个想法是,你会因为DNS过载而出错——也许你的解析器不允许你每次执行超过一定数量的查询。在</p>
<hr/>
<p>此外,我发现了一些问题:</p>
<ol>
<li><p>您忘了在<code>while</code>循环中正确地分配<code>site</code>这可能最好用在队列上迭代的<code>for</code>循环来代替。在您的版本中,您使用模块级命名空间中的<code>site</code>变量,这可能导致查询加倍,其他查询被跳过。在</p>
<p>在这种情况下,您可以控制队列是否仍有条目或等待一些条目。如果两者都不是,你可以退出你的线程。</p></li>
<li><p>出于安全考虑,你最好这样做</p>
<pre><code>def mexec(befehl, args=None):
cur = conn.cursor()
cur.execute(befehl, args)
</code></pre>
<p>为了以后做</p>
<pre><code>mexec("UPDATE sites2block SET ip=%s, updated='yes'", result) #puts site in mysqldb
</code></pre></li>
</ol>
<hr/>
<p>为了与未来的协议保持兼容,您应该使用<code>socket.getaddrinfo()</code>,而不是{<cd6>}。在那里你可以得到你想要的所有IP(一开始,你可以限制到IPv4,但是切换到IPv6就更容易了),并且可以将它们全部放入数据库。在</p>
<hr/>
<p>对于您的队列,代码示例可以是</p>
<pre><code>def queue_iterator(q):
"""Iterate over the contents of a queue. Waits for new elements as long as the queue is still filling."""
while True:
try:
item = q.get(block=q.is_filling, timeout=.1)
yield item
q.task_done() # indicate that task is done.
except Empty:
# If q is still filling, continue.
# If q is empty and not filling any longer, return.
if not q.is_filling: return
def getips(i, q):
for site in queue_iterator(q):
# resolve IP
try:
result = socket.gethostbyname_ex(site)
print(result)
mexec("UPDATE sites2block SET ip=%s, updated='yes'", result) #puts site in mysqldb
except (socket.gaierror):
print("no ip")
mexec("UPDATE sites2block SET ip='no ip', updated='yes',")
# Indicate it is filling.
q.is_filling = True
#Spawn thread pool
for i in range(num_threads):
worker = Thread(target=getips, args=(i, queue))
worker.setDaemon(True)
worker.start()
#Place work in queue
for site in websites:
queue.put(site)
queue.is_filling = False # we are done filling, if q becomes empty, we are done.
#Wait until worker threads are done to exit
queue.join()
</code></pre>
<p>应该会成功的。在</p>
<hr/>
<p>另一个问题是并行插入MySQL。一次只能执行一个MySQL查询。因此,您可以通过<code>threading.Lock()</code>或<code>RLock()</code>来保护访问,也可以将答案放入另一个由另一个线程处理的队列中,该队列甚至可以捆绑它们。在</p>