【问题标题】:Checking for IP addresses检查 IP 地址
【发布时间】:2012-08-03 09:43:29
【问题描述】:

是否有任何现有的库可以将字符串解析为 ipv4 或 ipv6 地址,或者至少识别字符串是否是 IP 地址(任何一种)?

【问题讨论】:

    标签: python ip ipv6


    【解决方案1】:

    是的,有ipaddr 模块,可以帮助您检查字符串是否为 IPv4/IPv6 地址,并检测其版本。

    import ipaddr
    import sys
    
    try:
       ip = ipaddr.IPAddress(sys.argv[1])
       print '%s is a correct IP%s address.' % (ip, ip.version)
    except ValueError:
       print 'address/netmask is invalid: %s' % sys.argv[1]
    except:
       print 'Usage : %s  ip' % sys.argv[0]
    

    但这不是一个标准模块,所以并不总是可以使用它。 您还可以尝试使用标准的socket 模块:

    import socket
    
    try:
        socket.inet_aton(addr)
        print "ipv4 address"
    except socket.error:
        print "not ipv4 address"
    

    对于 IPv6 地址,您必须使用 socket.inet_pton(socket.AF_INET6, address)

    我还想指出,inet_aton 将尝试转换(并真正转换)地址,例如10127 等,它们看起来不像 IP 地址。

    【讨论】:

    • AttributeError: 'module' 对象没有属性 'ip_address'
    • @Blazemore:在新版本的模块中使用IPAddress;修正了我的答案;谢谢你的建议!
    • 只是为了添加一点背景,套接字实现要快得多。
    • socket 实现要快得多,我有一个函数可以用端口测试 ipv4 或 ipv6。所以它必须调用 ipaddress 或 socket 来检查。在混合 IP 和大量调用的情况下,值得使用套接字: ipaddres: 127.0.0.1:5000 100000 运行 0.700674057007 ::1 100000 运行 0.607309103012 [::1]:5000 100000 运行 0.0515758909124 套接字 0027:ns。 0.172153949738 ::1 100000 次运行 0.0361239910126 [::1]:5000 100000 次运行 0.0545198917389
    • 请注意,自从发布此消息以来,ipaddr 现在是 ipaddress 并且是 Python 3 库以及 Python 2 反向端口标准的一部分:docs.python.org/3/library/ipaddress.html
    【解决方案2】:

    对于 IPv4,您可以使用

    socket.inet_aton(some_string)
    

    如果抛出异常,some_string 不是有效的 ip 地址

    对于 IPv6,您可以使用:

    socket.inet_pton(socket.AF_INET6, some_string)
    

    同样,如果some_string 不是有效地址,它会引发异常。

    【讨论】:

    • @Sven,我为v6添加了一个方法,只是稍微复杂一点
    • 这些是 Unix 唯一的解决方案。如果您正在寻找跨平台解决方案,它们将无法正常工作。
    【解决方案3】:

    仅依赖标准库的 IPv4 + IPv6 解决方案。返回46 或引发ValueError

    try:
        # Python 3.3+
        import ipaddress
    
        def ip_kind(addr):
            return ipaddress.ip_address(addr).version
    
    except ImportError:
        # Fallback
        import socket
    
        def ip_kind(addr):
            try:
                socket.inet_aton(addr)
                return 4
            except socket.error: pass
            try:
                socket.inet_pton(socket.AF_INET6, addr)
                return 6
            except socket.error: pass
            raise ValueError(addr)
    

    【讨论】:

      【解决方案4】:

      您可以使用netaddr 库。它有 valid_ipv4/valid_ipv6 方法:

      import netaddr
      if netaddr.valid_ipv4(str_ip) is True:
          print("IP is IPv4")
      else:
          if netaddr.valid_ipv6(str_ip) is True:
              print("IP is IPv6")
      

      【讨论】:

        【解决方案5】:

        试试

        apt-get install python-ipaddr
        

        或从here获取源代码

        【讨论】:

          【解决方案6】:

          ipaddr -- Google 的 IP 地址操作包。

          请注意,最近已接受在 Python 标准库中包含该包的修订版本的提议(请参阅 PEP 3144)。

          【讨论】:

          • 请注意,虽然这个库确实已被接受包含在标准库中,但它还没有包含在任何稳定的 Python 版本中。 (当然你仍然可以安装 PyPI 版本。)
          【解决方案7】:

          如果您确定地址是有效的,并且只是试图确定它是 ipv4 还是 ipv6,那么这样做还不够吗:

          if ":" in address:
              print("Ipv6")
          else:
              print("Ipv4")
          

          【讨论】:

          • 我不知道这是一个IP。我需要检查它是否是IP。为了清楚起见,我更新了问题。
          【解决方案8】:

          我更喜欢 ip_interface,因为它可以处理带有和不带有前缀掩码的情况,例如“10.1.1.1/24”和简单的“10.1.1.1”。不用说,适用于 v4 和 v6

          from ipaddress import ip_interface
          ip_interface("10.1.1.1/24").ip
          ip_interface("10.1.1.1/24").ip.version
          ip_interface("10.1.1.1").ip
          ip_interface("10.1.1.1").ip.version
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2013-07-29
            • 1970-01-01
            • 1970-01-01
            • 2013-08-22
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2012-11-28
            相关资源
            最近更新 更多