我有一个这样定义的线程类:
#!/usr/bin/python
import threading
import subprocess
class PingThread (threading.Thread):
ipstatus = ''
def __init__(self, ip):
threading.Thread.__init__(self)
self.ipaddress = ip
def ping(self, ip):
print 'Pinging ' + ip + '...'
ping_response = subprocess.Popen(["ping", "-c", "1", ip], stdout=subprocess.PIPE).stdout.read()
if '100.0% packet loss' not in str(ping_response):
return True
return False
def set_ip_status(self, status):
self.ipstatus = status
def get_ip_status(self):
return self.ipstatus
def run(self):
self.ipaddress = self.ipaddress.strip('\n\t')
pingResponse = self.ping(self.ipaddress)
if pingResponse:
self.set_ip_status(self.ipaddress + ' is up!')
else:
self.set_ip_status(self.ipaddress + ' is down!')
我正在查看IP地址列表,并将其发送到PingThread
,并让此类ping IP地址。这些线程全部完成后,我希望它通过调用get_ip_status()
来获得每个线程的状态。我的代码中有q.join()
,应该等到队列中的所有项目都完成后(据我了解,如果我错了,请更正我,仍然是线程新手),但是我的代码从未通过q.join
。我测试了所有线程,并完成了所有IP地址的ping操作,但是q.join()
无法识别。为什么是这样?我究竟做错了什么?我正在创建这样的线程:
q = Queue.Queue()
for ip in trainips:
thread = PingThread(ip)
thread.start()
q.put(thread)
q.join()
while not q.empty():
print q.get().get_ip_status()
python大神给出的解决方案
您误解了Queue.join
的工作原理。 Queue.join
旨在与Queue.task_done
一起使用;在生产者端,您将put
个项目放入一端的Queue
中,然后调用Queue.join
以等待处理您所有put
的项目。然后在消费者端,您从get
中Queue
一个项目,对其进行处理,然后在完成后调用Queue.task_done
。为所有已被task_done
放入put
的项目调用Queue
后,Queue.join
将解除阻止。
但是你没有那样做。您只是在启动一堆线程,将它们添加到Queue
,然后在其上调用join
。您根本不使用task_done
,而只是在Queue.get
之后调用Queue.join
,看起来您只是在用它来完成线程对象。但这不是真的。 Queue
不知道其中是否有Thread
对象,只需调用Queue.join
就不会等待其中的Thread
对象完成。
确实,看起来您需要做的就是将线程放入列表中,然后在每个线程上调用join
。
threads = []
for ip in trainips:
thread = PingThread(ip)
thread.start()
threads.append(thread)
for thread in threads:
thread.join()
print thread.get_ip_status()