【问题标题】:How to increment at different intervals python?如何以不同的间隔递增python?
【发布时间】:2018-12-06 19:43:26
【问题描述】:

假设我有一个 IP 地址192.168.1.1 我将如何以这样的不同间隔递增?

192.168.1.2
192.168.1.3

...一直到192.168.1.999,然后“翻转”到192.168.2.1

【问题讨论】:

  • @MoxieBall 这只是一个例子
  • 你是如何存储这个 IP 地址的?
  • @JacobBoertjes 作为字符串
  • 你想要一个函数,它接受一个 ip 字符串和一个间隔并将 ip 增加这么多吗?

标签: python ip-address


【解决方案1】:

您应该为此使用 stdlib ipaddress。不要试图用原始字符串操作来做,因为有几个陷阱和奇怪的边缘情况。使用面向对象的库可以防止生成无效数据。

将 ipv4 地址从 192.168.1.0 迭代到 192.168.1.255(含)相当于迭代 192.168.1.0/24 subnet。使用network 对象:

>>> from ipaddress import ip_network
>>> list(ip_network('192.168.1.0/24'))
[IPv4Address('192.168.1.0'),
 IPv4Address('192.168.1.1'),
 IPv4Address('192.168.1.2'),
...
 IPv4Address('192.168.1.255')]

其中一些地址不是可用的主机,例如 255 是broadcast address。如果这是您要查找的内容,请迭代 hosts

>>>> list(ip_network('192.168.1.0/24').hosts())
[IPv4Address('192.168.1.1'),
 IPv4Address('192.168.1.2'),
 IPv4Address('192.168.1.3'),
...
 IPv4Address('192.168.1.254')]

请注意,192.168.1.999 不是有效的 IP 地址,所以不要生成它!验证器将阻止您创建它:

>>> from ipaddress import ip_address
>>> ip_address('192.168.1.254')
IPv4Address('192.168.1.254')
>>> ip_address('192.168.1.999')
# ValueError: '192.168.1.999' does not appear to be an IPv4 or IPv6 address

要将ip address object 转换回普通的旧字符串,只需调用str 即可。

您的问题还询问了“翻转”到 192.168.2.1。这只是迭代不同的子网。 192.168.1.0/24 中的 24 是指为网络前缀分配的 24 位有效位(其余 8 位保留用于主机寻址),即 子网掩码 255.255.255.0。

为了让它“翻转”,你真的只想迭代一个更大的子网:

>>> gen = iter(ip_network('192.168.0.0/16'))
>>> for i in range(255*2):
...     next(gen)
...     
>>> next(gen)
IPv4Address('192.168.1.254')
>>> next(gen)
IPv4Address('192.168.1.255')
>>> next(gen)
IPv4Address('192.168.2.0')
>>> next(gen)
IPv4Address('192.168.2.1')

要从单个ip地址字符串获取网络对象,可以使用supernet方法:

>>> from ipaddress import ip_address, ip_interface
>>> ip = ip_address('192.168.1.1')
>>> net = ip_interface(ip).network
>>> net
IPv4Network('192.168.1.1/32')
>>> net.supernet(prefixlen_diff=8)
IPv4Network('192.168.1.0/24')

阅读 Internet Protocol version 4 了解更多信息,以及 Python 的 ipaddress 模块的官方文档。

【讨论】:

    【解决方案2】:
    for ip3 in range(1, 127):
        for ip4 in range(1, 999):
            ip = '.'.join("192", "68", str(ip3), str(ip4))
    

    这会给你这个想法吗?

    【讨论】:

    • 虽然这回答了确切的问题,但这会产生一些无效的 IP 地址。
    • @MatthewStory 我有一些东西可以解决这个问题,无论如何感谢您的评论。
    • @MatthewStory:我意识到了; OP 正在寻找增量解决方案。我假设他知道如何处理 IP 限制 - 感谢您强调潜在问题。
    【解决方案3】:
    # for IP addresses of the form 1.92.168.a.b
    
    a_max = 10
    b_max = 999
    
    ips = []
    for a in range(a_max):
        for b in range(b_max):
            ips += ['1.92.168.{}.{}'.format(a,b)]
    

    这将为您提供以字符串形式生成的所有 IP 地址的列表。

    【讨论】:

      【解决方案4】:

      您可以使用ip_address.split(.) 拆分地址,得到ip_list。跟踪您想到的限制。在转换为整数后增加ip_list 的每个元素,然后再转换回字符串并使用".".join(ip_list) 将它们全部重新组合在一起

      【讨论】:

        【解决方案5】:

        您可以使用__add__ 方法创建一个类:

        class Ip:
         def __init__(self, _ip:str, _stop = 999) -> None:
           self.ip = _ip
           self.stop = _stop
         def __add__(self, _val):
           _ip = list(map(int, self.ip.split('.')))
           _r = 0
           while _r < 4:
             result = _ip[3 -_r]+_val
             if result < self.stop:
               _ip[3 - _r] += _val
               break
             _ip[3 - _r] += _val%self.stop
             _val = _val%self.stop
             _r += 1
             _ip[4 - _r] = 1
           return Ip('.'.join(map(str, _ip)))
         def __repr__(self):
           return f'<IP {self.ip}>'
        
        p = Ip('192.168.1.1')
        new_p = p + 1
        print(new_p)
        print(p + 1000)
        

        输出:

        <IP 192.168.1.2>
        <IP 192.168.2.1>
        

        【讨论】:

        猜你喜欢
        • 2020-03-28
        • 1970-01-01
        • 2019-12-23
        • 2022-11-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-07-05
        • 2018-10-16
        相关资源
        最近更新 更多