【问题标题】:python ipaddress, get first usable host only?python ipaddress,仅获取第一个可用主机?
【发布时间】:2016-09-28 15:19:59
【问题描述】:

我正在使用 pythons ipaddress 模块,我试图只获取第一个可用的主机,而不是所有可用的主机

下面给了我所有的主机,当我尝试索引它时,我得到了下面的错误。

是否有可能通过其他方式获得第一个可用的主机?

谢谢

n = ipaddress.ip_network(u'10.10.20.0/24')
for ip in n.hosts():
...  print ip
10.10.20.1
10.10.20.2
10.10.20.3
10.10.20.4
...
>>> for ip in n.hosts():
...  print ip[1]
...
Traceback (most recent call last):
  File "<console>", line 2, in <module>
TypeError: 'IPv4Address' object does not support indexing
>>>

下面的也失败了

>>> print n.hosts()[0]
Traceback (most recent call last):
  File "<console>", line 1, in <module>
TypeError: 'generator' object has no attribute '__getitem__'

【问题讨论】:

  • ip 已经是列表中的单个 IP,您希望 ip[1] 返回什么?

标签: python ip-address


【解决方案1】:

hosts() 返回一个不支持索引的生成器对象。您必须遍历它。

如果你只想要第一个元素,只需使用next()

n = ipaddress.ip_network(u'10.10.20.0/24')
first_host = next(n.hosts())

如果要将生成器对象转换为支持索引的列表,则必须调用list()函数:

all_hosts = list(n.hosts())
first_host = all_hosts[0]

您还可以像循环列表一样遍历生成器对象,就像您在第一个代码 sn-p 中所做的那样:

for ip in n.hosts():
    # do something with ip: this is the IP address, so don't try to index into it!
    pass

【讨论】:

    【解决方案2】:

    短版:

    import ipaddress
    net=ipaddress.ip_network(u'1.0.0.0/8')
    first=str(net[1])
    last=str(net[-2])
    

    长版:

    这显示了计算第一个和最后一个可用 IP 地址的 3 种方法 在使用 ipaddress 的 CIDR 块中。

    它显示了“正确”(快速、节省空间的方法) 和另外两个使用主机迭代器,结果是 说明一个经典的时空权衡。

    import ipaddress
    import time
    import sys
    
    #
    # The fast, memory efficient way
    #
    
    start = time.time()
    
    net=ipaddress.ip_network(u'1.0.0.0/8')
    first=str(net[1])
    last=str(net[-2])
    
    stop = time.time()
    seconds=stop-start
    size=sys.getsizeof(net)
    
    print("First Host: %s, Last Host: %s, Seconds: %.4f, Size (Mb): %d" % (first,last, seconds, size/(1024**2)))
    
    #
    # Space efficient, but slow
    #
    
    start = time.time()
    
    net=ipaddress.ip_network(u'1.0.0.0/8')
    iterator=ipaddress.ip_network(u'1.0.0.0/8').hosts()
    first = last = next(iterator, None)
    for last in iterator:
        pass
    first=str(first)
    last=str(last)
    
    stop = time.time()
    seconds=stop-start
    size=sys.getsizeof(net)
    
    print("First Host: %s, Last Host: %s, Seconds: %.4f, Size (Mb): %d" % (first,last, seconds, size/(1024**2)))
    
    
    
    #
    # Memory hog and slow, the worst of both worlds.
    #
    
    start = time.time()
    
    hosts=list(ipaddress.ip_network(u'1.0.0.0/8').hosts())
    first_host=str(hosts[0])
    last_host=str(hosts[-1])
    size=sys.getsizeof(hosts)
    
    stop = time.time()
    seconds=stop-start
    print("First Host: %s, Last Host: %s, Seconds: %.4f, Size (Mb): %d" % (first,last, seconds, size/(1024**2)))
    
    First Host: 1.0.0.1, Last Host: 1.255.255.254, Seconds: 0.0000, Size (Mb): 0
    First Host: 1.0.0.1, Last Host: 1.255.255.254, Seconds: 8.0086, Size (Mb): 0
    First Host: 1.0.0.1, Last Host: 1.255.255.254, Seconds: 11.8096, Size (Mb): 132
    

    【讨论】:

      【解决方案3】:

      获取第一个主机地址的替代方法尤其是对于“大网络”/小前缀值是:

      In [2]: ip_network("10.10.20.0/24")[1]
      Out[2]: IPv4Address('10.10.20.1')
      

      根本不需要使用 hosts() 生成器。参见例如https://docs.python.org/3/library/ipaddress.html#networks-as-containers-of-addresses 关于 ipaddress 网络对象作为“地址容器”。此地址空间/“地址容器”中的第一个地址是网络地址(索引 [0])。最后一个地址是广播地址(索引 [-1])。

      或者你可以使用网络地址并通过加1得到第一个主机地址:

      In [4]: ip_network("10.10.20.0/24").network_address + 1
      Out[4]: IPv4Address('10.10.20.1')
      

      根据您使用的前缀/网络掩码,hosts() 生成器可能很慢。如果你使用

      list(ip_network("10.0.0.0/8").hosts())
      

      该语句创建一个包含 2**(32-8) - 2 = 16777214 个条目的列表

      如果我为这个语句计时,它需要 > 10 秒来创建这个主机列表:

      In [11]: %time len(list(ip_network("10.0.0.0/8").hosts()))
      Wall time: 13.6 s
      Out[11]: 16777214
      

      如果我比较获取第一个地址所需的时间:

      In [15]: %time list(ip_network("10.0.0.0/8").hosts())[0]
      Wall time: 13.6 s
      Out[15]: IPv4Address('10.0.0.1')
      In [13]: %timeit -n10 -r5 ip_network("10.0.0.0/8")[1]
      10 loops, best of 5: 11.8 µs per loop
      In [17]: %timeit -n10 -r5 ip_network("10.0.0.0/8").network_address + 1
      10 loops, best of 5: 9.16 µs per loop
      

      结果:hosts() 大约需要 14 秒才能完成。替代方案是 +/- 10 µs

      /24 网络的时间:

      In [19]: %timeit -n10 -r5 list(ip_network("10.0.0.0/24").hosts())[0]
      10 loops, best of 5: 135 µs per loop
      
      In [20]: %timeit -n10 -r5 ip_network("10.0.0.0/24").network_address + 1
      10 loops, best of 5: 9.32 µs per loop
      

      【讨论】:

        猜你喜欢
        • 2013-12-01
        • 2016-06-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-01-27
        • 1970-01-01
        • 2011-02-03
        • 1970-01-01
        相关资源
        最近更新 更多