为什么即使在线程化之后该程序也会花费这么多时间?

时间:2015-11-27 18:48:02

标签: python multithreading

我一直在尝试查找连接到具有特定掩码的网关的活动主机,但即使在线程化之后也需要花费很多时间。总主机也显示不正确。

CODE是:

import subprocess, sys, threading, time, queue

t = 0
[a,b,c,d] = list(sys.argv[1].split("."))
mask = int(sys.argv[2])
p = queue.Queue()

def alive(host):
    reply = str(subprocess.Popen(["ping", "-n","1","-w","5",host],
                          stdout=subprocess.PIPE).communicate()[0])

    if "TTL=" in reply :
        if host != sys.argv[1]:
            print(host," is UP")
            p.put(1)
        else:
            p.put(0)
    else:
        p.put(0)

start_time = time.time()

if mask == 8:
    for i in range(1,256):
        for j in range(1,256):
            for k in range(1,256):
                iplist = [a,str(i),str(j),str(k)]
                ip = '.'.join(iplist)
                thread = threading.Thread(target = alive(ip))
                thread.start()

elif mask == 16:
    for i in range(1,256):
        for j in range(1,256):
                iplist = [a,b,str(i),str(j)]
                ip = '.'.join(iplist)
                thread = threading.Thread(target = alive(ip))
                thread.start()

elif mask == 24:
    for i in range(1,256):
        iplist = [a,b,c,str(i)]
        ip = '.'.join(iplist)
        thread = threading.Thread(target = alive(ip))
        thread.start()

else:
    print("Mask must be 8 , 16 or 24")

for i in range(p.qsize()):
    if p.get == 1:
        t+=1
    else:
        pass

print("\nTotal no. of hosts connected to ",sys.argv[1], " is ",t)
print("Total time taken is ",time.time() - start_time)

命令行输入:

python uphost.py 192.168.1.1 24

输出:

192.168.1.20  is UP
192.168.1.30  is UP

Total no. of hosts connected to  192.168.1.1  is  0
Total time taken is  125.90091395378113

2 个答案:

答案 0 :(得分:2)

您正在创建太多线程(256,256 ^ 2,256 ^ 3)。并且线程创建有一个开销,你需要平衡每个线程正在做的工作量。

我认为更好的解决方案是使用预定数量的线程池(请参阅https://docs.python.org/2/library/multiprocessing.html#module-multiprocessing.pool)(与您的机器支持的线程数一样多)。

答案 1 :(得分:0)

除了上面提到的使用太多线程的问题之外,你的实际问题(125秒)是你因为这个而没有使用线程进行ping命令

elif mask == 24:
    for i in range(1, 256):
        iplist = [a, b, c, str(i)]
        ip = '.'.join(iplist)
        thread = threading.Thread(target=alive(ip))
        thread.start()

您正在主线程中调用alive(ip),并且该调用的返回是生成线程的目标..

你想做的是

elif mask == 24:
    for i in range(1, 256):
        iplist = [a, b, c, str(i)]
        ip = '.'.join(iplist)
        thread = threading.Thread(target=alive, args=[ip])
        thread.start()

这是您的代码(非线程)的第一个问题。

修复后,您会发现另一个问题。您并没有等待线程完成,所以:

...
threads = []
...
elif mask == 24:
    for i in range(1, 25):
        iplist = [a, b, c, str(i)]
        ip = '.'.join(iplist)
        thread = threading.Thread(target=alive, args=[ip])
        threads.append(thread)
        thread.start()

...

for thread in threads:
    thread.join()

for i in range(p.qsize()):
    if p.get() == 1:
        t += 1
    else:
        pass

此处添加的拼写错误修正为p.get(不含())。

但你应该像{simpel01那样关注multiprocessing.Pool,因为它更简单,更清晰,使用和管理线程池而不是进入spawn-frenzy模式:)

编辑>使用multiprocessing.Pool更新代码

import subprocess
import sys
import multiprocessing
import time

[a, b, c, d] = list(sys.argv[1].split("."))
mask = int(sys.argv[2])


def alive(host):
    reply = str(
        subprocess.Popen(
            ["ping", "-c", "1", "-t", "5", host],  # edited for linux
            stdout=subprocess.PIPE
        ).communicate()[0]
    )

    if "ttl=" in reply:
        if host != sys.argv[1]:
            print(host, " is UP")
            return host

    return None


def main():
    ips = []
    if mask == 8:
        for i in range(1, 256):
            for j in range(1, 256):
                for k in range(1, 256):
                    iplist = [a, str(i), str(j), str(k)]
                    ips.append('.'.join(iplist))
    elif mask == 16:
        for i in range(1, 256):
            for j in range(1, 256):
                    iplist = [a, b, str(i), str(j)]
                    ips.append('.'.join(iplist))
    elif mask == 24:
        for i in range(1, 256):
            iplist = [a, b, c, str(i)]
            ips.append('.'.join(iplist))
    else:
        print("Mask must be 8 , 16 or 24")
        return

    start_time = time.time()
    pool = multiprocessing.Pool(processes=100)
    hosts_up = [x for x in pool.map(alive, ips) if x]

    print("\nTotal no. of hosts connected to ", sys.argv[1], " is ", len(hosts_up))
    print("Total time taken is ", time.time() - start_time)

if __name__ == '__main__':
    main()

结果

$ python3 uphosts.py 192.168.1.1 24
192.168.1.66  is UP
192.168.1.65  is UP
192.168.1.254  is UP

Total no. of hosts connected to  192.168.1.1  is  3
Total time taken is  15.280648946762085