【问题标题】:Retrieving network mask in Python在 Python 中检索网络掩码
【发布时间】:2010-10-30 12:04:32
【问题描述】:

如何检索网络设备的网络掩码(最好在 Linux 中,但如果它是跨平台的,那就太棒了)?我知道如何在 Linux 上使用 C,但我在 Python 中找不到方法——也许减去 ctypes。那或解析ifconfig。还有什么办法吗?

ioctl(socknr, SIOCGIFNETMASK, &ifreq) // C version

【问题讨论】:

    标签: python


    【解决方案1】:

    This 在 Linux 上的 Python 2.2 中为我工作:

    iface = "eth0"
    socket.inet_ntoa(fcntl.ioctl(socket.socket(socket.AF_INET, socket.SOCK_DGRAM), 35099, struct.pack('256s', iface))[20:24])
    

    【讨论】:

    • 谢谢。我正在寻找 op 值。
    • 这是否适用于纯 IPv6 网络?
    【解决方案2】:

    netifaces 模块在这里值得一提。直接来自文档:

    >>> netifaces.interfaces()
    ['lo0', 'gif0', 'stf0', 'en0', 'en1', 'fw0']
    
    >>> addrs = netifaces.ifaddresses('en0')
    >>> addrs[netifaces.AF_INET]
    [{'broadcast': '10.15.255.255', 'netmask': '255.240.0.0', 'addr': '10.0.1.4'}, {'broadcast': '192.168.0.255', 'addr': '192.168.0.47'}]
    

    适用于 Windows、Linux、OS X 和可能的其他 UNIX。

    【讨论】:

    • 谢谢。像我一样开始一个子流程,效果很好,也更容易。
    【解决方案3】:

    你看过这里吗?

    http://docs.python.org/library/fcntl.html

    这适用于我在 Linux 上的 python 2.5.2 中。 Ben 领先时正在完成它,但它仍然在这里(可悲的是浪费了努力:-)):

    vinko@parrot:~$ more get_netmask.py
    # get_netmask.py by Vinko Vrsalovic 2009
    # Inspired by http://code.activestate.com/recipes/439093/
    # and http://code.activestate.com/recipes/439094/
    # Code: 0x891b SIOCGIFNETMASK
    
    import socket
    import fcntl
    import struct
    import sys
    
    def get_netmask(ifname):
            s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
            return socket.inet_ntoa(fcntl.ioctl(s.fileno(), 0x891b, struct.pack('256
    s',ifname))[20:24])
    
    if len(sys.argv) == 2:
            print get_netmask(sys.argv[1])
    vinko@parrot:~$ python get_netmask.py lo
    255.0.0.0
    vinko@parrot:~$ python get_netmask.py eth0
    255.255.255.0
    

    【讨论】:

    • 不,没看到那个。甜的。谢谢。
    【解决方案4】:

    您可以使用此库:http://github.com/rlisagor/pynetlinux。注意:我是图书馆的作者。

    【讨论】:

      【解决方案5】:

      我的想法是依靠子进程使用简单的 ifconfig (Linux) 或 ipconfig (windows) 请求来检索信息(如果 ip 已知)。 欢迎评论

      Windows

      ip = '192.168.1.10' #Example
      proc = subprocess.Popen('ipconfig',stdout=subprocess.PIPE)
      while True:
          line = proc.stdout.readline()
          if ip.encode() in line:
              break
      mask = proc.stdout.readline().rstrip().split(b':')[-1].replace(b' ',b'').decode()
      

      类 UNIX

      ip = '192.168.1.10' #Example
      proc = subprocess.Popen('ifconfig',stdout=subprocess.PIPE)
      while True:
          line = proc.stdout.readline()
          if ip.encode() in line:
              break
      mask = line.rstrip().split(b':')[-1].replace(b' ',b'').decode()
      

      使用与网络的套接字连接并使用getsockname()[0] 检索IP

      【讨论】:

      • ifconfig 不再总是预先安装在 linux 上,新命令是 ip addr
      • @Typewar,ip addr 是否预装在旧的 linux 版本上?
      【解决方案6】:

      在 Windows 中,这段代码可能有用:

      import os
      import sys
      import _winreg
      
      
      def main():
          adapter_list_key = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE,
              r'SOFTWARE\Microsoft\Windows NT\CurrentVersion\NetworkCards')
      
          adapter_count = _winreg.QueryInfoKey(adapter_list_key)[0]
      
          for i in xrange(adapter_count):
              sub_key_name = _winreg.EnumKey(adapter_list_key, i)
              adapter_key = _winreg.OpenKey(adapter_list_key, sub_key_name)
              (adapter_service_name, _) = _winreg.QueryValueEx(adapter_key, "ServiceName")
              (description, _) = _winreg.QueryValueEx(adapter_key, "Description")
      
              adapter_registry_path = os.path.join(r'SYSTEM\ControlSet001\Services',
                  adapter_service_name, "Parameters", "Tcpip")
              adapter_service_key = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE,
                  adapter_registry_path)
              (subnet_mask, _) = _winreg.QueryValueEx(adapter_service_key, "SubnetMask")
              (ip_address, _) = _winreg.QueryValueEx(adapter_service_key, "IpAddress")
      
              sys.stdout.write("Name: %s\n" % adapter_service_name)
              sys.stdout.write("Description: %s\n" % description)
              sys.stdout.write("SubnetMask: %s\n" % subnet_mask)
              sys.stdout.write("IpAdress: %s\n" % ip_address)
      
      
      if __name__ == "__main__":
          main()
      

      HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\NetworkCards 注册表项中获取网络适配器列表,然后从HKLM\SYSTEM\ControlSet001\Services\{adapter_guid}\Parameters\Tcpip 项中提取有关每个适配器的更多信息。

      我在带有 2 个虚拟适配器的 Windows XP 上对其进行了测试,它运行良好。应该可以在 2000、2003 和 Vista 中使用。

      【讨论】:

      • 我添加了 Py3 compat(没什么大不了的)和 DHCP(对我来说很重要)。也使用CurrentControlSet。我复制了一份here,因为它太长了,无法发表评论。
      【解决方案7】:

      使用python pyroute2库可以获取所有网元属性:

      from pyroute2 import IPRoute
      ip = IPRoute()
      info = [{'iface': x['index'], 'addr': x.get_attr('IFA_ADDRESS'), 'mask':  x['prefixlen']} for x in ip.get_addr()]
      

      更多信息在这里:http://pyroute2.org/pyroute2-0.3.14p4/iproute.html

      【讨论】:

        【解决方案8】:

        我将原始答案作为原始代码进行了更新:

        struct.pack('256s', iface)
        

        在 Python 3.9 中抛出错误,所以这里是一个重新审视的版本:

        
            SIOCGIFADDR = 0x8915
        
            def get_iface_ip(iface: str):
                """
                Get network interface IP using the network interface name
                :param iface: Interface name (like eth0, enp2s0, etc.)
                :return IP address in the form XX.XX.XX.XX
                """
                with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s:
                    iface_bin = struct.pack('256s', bytes(iface, 'utf-8'))
                    packet_ip = fcntl.ioctl(s.fileno(), SIOCGIFADDR, iface_bin)[20:24]
                return socket.inet_ntoa(packet_ip)
        

        【讨论】:

          【解决方案9】:

          您可以通过在 CMD 上运行命令并提取相关信息来实现此目的。

          我的实现:

          import subprocess
          
          p = subprocess.Popen('ipconfig', shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
          
          for line in p.stdout.readlines():
            if b'Subnet Mask' in line:
             print(line.decode().split(' ')[-1].strip('\r\n'))
          

          【讨论】:

            【解决方案10】:

            使用socketipaddress

            来自文档

            ipaddress 提供在 IPv4 和 IPv6 地址和网络上创建、操作和操作的功能。
            此模块中的函数和类可以直接处理与 IP 地址相关的各种任务 ...

            >>> import socket
            >>> import ipaddress
            >>>
            >>> ip_addr = socket.gethostbyname(socket.gethostname())
            >>> netmask = ipaddress.IPv4Network(ip_addr).netmask
            >>> print(netmask)
            255.255.255.255
            >>> ...
            

            这个问题可以回答here。这不是同一个问题,但也为您的问题提供了解决方案。

            【讨论】:

            • 你确定这是网络掩码吗?
            • 什么意思?,netmask和subnet mask是一样的
            • 嗨@torswq!我这么说是因为它在每种情况下都给出了“255.255.255.255”。我的网络掩码是“255.255.255.0”,但它输出“255.255.255.255”。
            • "来自文档":docs.python.org/3/library/ipaddress.html#ipaddress.IPv4Network "If no mask is provided, it’s considered to be /32." 并且gethostbyname 从不附加子网前缀长度。所以你总是会得到255.255.255.255。模块ipaddress是一个纯计算库,不会从系统中查找缺失的信息。
            • 我将删除这个问题,因为它没有帮助并且提供了错误的信息,很抱歉造成混淆
            猜你喜欢
            • 2012-07-12
            • 1970-01-01
            • 2012-12-16
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2016-12-27
            相关资源
            最近更新 更多