首页 > 解决方案 > ping LAN 的 Python 函数未将结果存储在全局列表中

问题描述

我正在尝试编写一个小脚本以基本上具有诸如 nmap (非常简单的脚本)之类的功能,并且我正在取得进展,但被困在其中的一个愚蠢的部分。

我认为这对我来说是一个很好的学习 python 的时刻。

该脚本成功地 ping 整个子网并打印出有关哪些主机响应的信息。我的下一步是将这些 IP 存储到列表中以供以后处理。这就是我卡住的地方:live_hosts 总是返回空。在函数中打印列表确实会显示当前活动的 IP,但会在每次新调用时被覆盖,然后在 map() 函数完成后完全为空。

import subprocess
import multiprocessing
import ipaddress
# import platform
import socket


#Getting information about network
def get_ip():
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    try:
        # doesn't even have to be reachable
        s.connect(('10.255.255.255', 1))
        IP = s.getsockname()[0]    
    except Exception:
        IP = '127.0.0.1'
    finally:
        s.close()
    return IP

host = get_ip()
octets = host.split(".")
subnet = ''

for octet in octets:
    if octet == octets[-1]:
        subnet = subnet[:-1] + "."
        break
    else:
        subnet = subnet + octet + "."

#pinging hosts on network to check for life

ips = (subnet+'%d' % i for i in range(1, 255))
**live_hosts = []**

def ping(ip,live_hosts=live_hosts):

    ping = subprocess.call(["ping", "-W", "1", "-c", "1", ip],
    stdout=subprocess.DEVNULL,
    stderr=subprocess.DEVNULL
    )
    
    if ping == 0:
        print(ip +" is up!")
        live_hosts.append(ip)
        return live_hosts

with multiprocessing.Pool(200) as p:
    p.map(ping,ips)  
    **print(live_hosts)**

我尝试将 live_hosts 包含为全局变量,创建一个临时列表并将其指向 live_hosts,但没有运气。

我不知道我错过了什么,非常感谢一些建议!谢谢。我知道我也可以更加 Pythonic,所以也欢迎任何 Pythonic 建议!

标签: python

解决方案


live_hosts每个工作人员通过 访问全局列表时p.map(ping,ips),它被复制到该工作人员的范围内。当工人第一次出现时,该列表将为空。

然后,worker 中的每个调用都append()对其自己的副本执行操作,并返回其副本的当前值live_hosts

您的调用map()不会捕获返回值。

做到这一点的正确方法是没有全局live_hosts列表,没有live_hostsin ping(),并且只ping()返回ip主机是否可达。

然后用live_hosts = p.map(ping, ips).

我认为它会充满很多空值,所以使用列表推导来过滤掉它们:

live_hosts = [x for x in p.map(ping,ips) if x != None]

关于性能,调用ping()时间最长的是那些只坐在那里等待一秒钟 ( -W 1) 以 ping 不存在的主机超时的调用。

由于您的目标代码被硬编码为假定 /24(C 类)并尝试 ping 该假定子网中的每个主机,因此您也可以将池大小增加到 254 或将其减少到 127。

map()除非您有一个填充良好的子网,否则您的整个脚本可能会在操作完成之前等待两次超时。

我会将池大小增加到 254 并将调用更改为 ping 以使用-W 2或更高,以更好地调查您的网络。


推荐阅读