Python多线程PING工具


最近用python写了一个PING工具,使用了两种写法,非OOP与OOP。

一、非OOP代码

#!/usr/bin/env python
from threading import Thread
import subprocess
from Queue import Queue

#指定线程数量
num_threads = 3
#申明一个队列
queue = Queue()
ips = [ "172.18.17.34", "172.18.17.35", "172.18.0.250", "10.10.11.250"]

#定义一个pinger方法
def pinger(i, q):
        #利用无限循环处理完队列
         while True:
                #从队列从取出ip
                ip = q.get()
                print "Thread %s: Pinging %s" % (i, ip)
                #执行ping命令并保存返回码
                ret = subprocess.call( "ping -c 1 -W 1 %s" % ip,
                                                shell=True,
                                                stdout=open('/dev/ null', 'w'),
                                                stderr=subprocess.STDOUT)
                 if ret == 0:
                        print "%s: is alive" % ip
                 else:
                        print "%s: did not respond" % ip
                #循环结束标志
                q.task_done()

#定义一个线程池
for i in range(num_threads):
        #指定pinger为线程目标
        worker = Thread(target=pinger, args=(i, queue))
        #防止线程挂起
        worker.setDaemon(True)
        #开启线程
        worker.start()

#程序运行控制点
for ip in ips:
        queue.put(ip)

print "Main Thread Waiting"
#等待所有线程运行完毕
queue.join()

二、OOP代码

import threading
import subprocess
import Queue

num_threads = 3
queue = Queue.Queue()
ips =  [ "172.18.17.34",  "172.18.17.35",  "172.18.0.250",  "10.10.11.250 "]

#定义一个threading.Thread的子类ThreadPING
class ThreadPING(threading.Thread):
                def __init__(self, i, queue):
                     #重写父类的构造函数前需要调用父类的__init__方法
                     threading.Thread.__init__(self)
                     #处理传进来的参数                                
                     self.i = i
                     self.queue = queue
                def run(self):
                     while True:
                          ip = self.queue.get()
                          print "Thread %s: Pinging %s" % (self.i, ip)
                           ret = subprocess.call( "ping -c 1 -W 1 %s" % ip,
                                                      shell=True,
                                                      stdout=open('/dev/ null', 'w'),
                                                      stderr=subprocess.STDOUT) 
                          if ret == 0:
                               print "%s: is alive" % ip
                          else:
                               print "%s: did not respond" % ip
                          self.queue.task_done()

#定义一个主函数
def main():            
                for i in range(num_threads):
                     t = ThreadPING(i,queue)
                     t.setDaemon(True)
                     t.start()
                for ip in ips:
                      queue.put(ip)
                print "Main Thread Waiting"
                queue.join()

#提供模块化调用
if __name__ == "__main__":
                main()

以上脚本中有硬代码,使用起来不够灵活,每次都需要修改代码中的ip列表,下面是改进后的代码(增加IP配置文件):

#!/usr/bin/env python
import threading
import subprocess
import Queue
import ConfigParser

num_threads = 15
queue = Queue.Queue()

class ThreadPING(threading.Thread):
                def __init__(self, i, queue):
                        threading.Thread.__init__(self)
                        self.i = i
                        self.queue = queue
                def run(self):
                        while True:
                             ip = self.queue.get()
                             ret = subprocess.call( "ping -c 1 -W 1 %s" % ip,
                                                      shell=True,
                                                      stdout=open('/dev/ null', 'w'),
                                                      stderr=subprocess.STDOUT) 
                             if ret == 0:
                                   print "%s: is alive" % ip
                             else:
                                   print "%s: did not respond" % ip
                              self.queue.task_done()

def main():
     #读取配置文件
     def readConfig(file="config.ini"):
            ips = []
            Config = ConfigParser.ConfigParser()
            Config.read(file)
            machines = Config.items("MACHINES")
            for ip in machines:
                 ips.append(ip[1])
            return ips
      ips = readConfig()
            for i in range(num_threads):
                 t = ThreadPing(i,queue)
                 t.setDaemon(True)
                 t.start()
            for ip in ips:
                 queue.put(ip)
            print "Main Thread Waiting"
            queue.join()

if __name__ == "__main__":
                main()

最后新建一个config.ini配置文件就行了:
[MACHINES]
server1:172.18.17.34
server2:172.18.17.35
server3:172.18.0.250
server4:10.10.11.250


个人总结:
对比两种写法可以发现OOP方式结构清晰、层次分明利于模块化调用,因此本人推荐使用OOP方式写python脚本。

你可能感兴趣的:(PING工具)