Python线程重复的字典结果

时间:2018-02-22 04:02:56

标签: python python-multithreading

我正在尝试通过线程调试ping主机列表的代码。

在类的第一次start()调用中,结果很好。 在随后的调用(start())中,我在dictionnary中得到重复。

示例结果:

  

INFO: main :[u'192.168.1.71',u'192.168.1.70']

     

信息:主要:启动看门狗,轮询间隔设置为15分钟/ 15秒

     

INFO: main :set([u'192.168.1.71',u'192.168.1.70'])

     

信息:主要:Ping IP ...

     

INFO: main :{'dead':[u'192.168.1.70',u'192.168.1.70'],'alive':[u'192.168.1.71',u'192.168 .1.71' ]}

     

信息:主要:休眠...

任何人都可以提供帮助吗?

#!/usr/bin/env python

import subprocess
import threading

class Pinger(object):

    status = {'alive': [], 'dead': []} # Populated while we are running

    hosts = [] # List of all hosts/ips in our input queue

    # How many ping process at the time.
    thread_count = 4

    # Lock object to keep track the threads in loops, where it can potentially be race conditions.
    lock = threading.Lock()

    def ping(self, ip):
        # Use the system ping command with count of 1 and wait time of 1.
        ret = subprocess.call(['ping', '-c', '2', '-W', '1', ip],
                          stdout=open('/dev/null', 'w'), 
        stderr=open('/dev/null', 'w'))

        return ret == 0 # Return True if our ping command succeeds

    def pop_queue(self):
        ip = None

        self.lock.acquire() # Grab or wait+grab the lock.

        if self.hosts:
            ip = self.hosts.pop()

        self.lock.release() # Release the lock, so another thread could grab it.

        return ip

    def dequeue(self):
        while True:
            ip = self.pop_queue()

            if not ip:
                return None

            result = 'alive' if self.ping(ip) else 'dead'
            self.status[result].append(ip)

    def start(self):
        threads = []

        for i in range(self.thread_count):
            # Create self.thread_count number of threads that together will
            # cooperate removing every ip in the list. Each thread will do the
            # job as fast as it can.
            t = threading.Thread(target=self.dequeue)
            t.start()
            threads.append(t)


        # Wait until all the threads are done. .join() is blocking.
        [ t.join() for t in threads ]

        return self.status

if __name__ == '__main__':
    ping = Pinger()
    ping.thread_count = 8
    ping.hosts = [
        '10.0.0.1', '10.0.0.2', '10.0.0.3', '10.0.0.4', '10.0.0.0', 
        '10.0.0.255', '10.0.0.100', 'google.com', 'github.com', 
        'nonexisting', '127.0.1.2', '*not able to ping!*', '8.8.8.8'
    ]

    print ping.start()

1 个答案:

答案 0 :(得分:0)

使用multiprocessing.Pool会让您的生活更轻松。你可以用以下方法完成同样的事情:

import multiprocessing
import subprocess

hosts = [
    '10.0.0.1', '10.0.0.2', '10.0.0.3', '10.0.0.4', '10.0.0.0', '10.0.0.255', '10.0.0.100',
    'google.com', 'github.com', 'nonexisting', '127.0.1.2', '*not able to ping!*', '8.8.8.8'
]

def ping(host):
    print("pinging", host)
    ret = subprocess.call(['ping', '-c', '2', '-W', '1', host],
                          stdout=open('/dev/null', 'w'), stderr=open('/dev/null', 'w'))
    return (host, ret == 0)

pool = multiprocessing.Pool(processes=8)

out = {'dead': [], 'alive': []}

for host, alive in pool.map(ping, hosts):
    if alive:
        out['alive'].append(host)
    else:
        out['dead'].append(host)

print(out)

如果由于某种原因你需要使用线程而不是进程,你可以通过(命名不当)multiprocessing.dummy.Pool而不是multiprocessing.Pool使用相同的功能:

from multiprocessing.dummy import Pool

否则,用法完全相同。