Finding local IP addresses using Python's stdlib

后端 未结 30 2436
北恋
北恋 2020-11-21 23:54

How can I find local IP addresses (i.e. 192.168.x.x or 10.0.x.x) in Python platform independently and using only the standard library?

相关标签:
30条回答
  • 2020-11-22 00:30

    One simple way to produce "clean" output via command line utils:

    import commands
    ips = commands.getoutput("/sbin/ifconfig | grep -i \"inet\" | grep -iv \"inet6\" | " +
                             "awk {'print $2'} | sed -ne 's/addr\:/ /p'")
    print ips
    

    It will show all IPv4 addresses on the system.

    0 讨论(0)
  • 2020-11-22 00:30

    This will work on most linux boxes:

    import socket, subprocess, re
    def get_ipv4_address():
        """
        Returns IP address(es) of current machine.
        :return:
        """
        p = subprocess.Popen(["ifconfig"], stdout=subprocess.PIPE)
        ifc_resp = p.communicate()
        patt = re.compile(r'inet\s*\w*\S*:\s*(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})')
        resp = patt.findall(ifc_resp[0])
        print resp
    
    get_ipv4_address()
    
    0 讨论(0)
  • 2020-11-22 00:32

    A Python 3.4 version utilizing the newly introduced asyncio package.

    async get_local_ip():
        loop = asyncio.get_event_loop()
        transport, protocol = await loop.create_datagram_endpoint(
            asyncio.DatagramProtocol,
            remote_addr=('8.8.8.8', 80))
        result = transport.get_extra_info('sockname')[0])
        transport.close()
        return result
    

    This is based on UnkwnTech's excellent answer.

    0 讨论(0)
  • 2020-11-22 00:33

    im using following module:

    #!/usr/bin/python
    # module for getting the lan ip address of the computer
    
    import os
    import socket
    
    if os.name != "nt":
        import fcntl
        import struct
        def get_interface_ip(ifname):
            s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
            return socket.inet_ntoa(fcntl.ioctl(
                    s.fileno(),
                    0x8915,  # SIOCGIFADDR
                    struct.pack('256s', bytes(ifname[:15], 'utf-8'))
                    # Python 2.7: remove the second argument for the bytes call
                )[20:24])
    
    def get_lan_ip():
        ip = socket.gethostbyname(socket.gethostname())
        if ip.startswith("127.") and os.name != "nt":
            interfaces = ["eth0","eth1","eth2","wlan0","wlan1","wifi0","ath0","ath1","ppp0"]
            for ifname in interfaces:
                try:
                    ip = get_interface_ip(ifname)
                    break;
                except IOError:
                    pass
        return ip
    

    Tested with windows and linux (and doesnt require additional modules for those) intended for use on systems which are in a single IPv4 based LAN.

    The fixed list of interface names does not work for recent linux versions, which have adopted the systemd v197 change regarding predictable interface names as pointed out by Alexander. In such cases, you need to manually replace the list with the interface names on your system, or use another solution like netifaces.

    0 讨论(0)
  • 2020-11-22 00:33
    import socket
    [i[4][0] for i in socket.getaddrinfo(socket.gethostname(), None)]
    
    0 讨论(0)
  • 2020-11-22 00:33

    netifaces is available via pip and easy_install. (I know, it's not in base, but it could be worth the install.)

    netifaces does have some oddities across platforms:

    • The localhost/loop-back interface may not always be included (Cygwin).
    • Addresses are listed per-protocol (e.g., IPv4, IPv6) and protocols are listed per-interface. On some systems (Linux) each protocol-interface pair has its own associated interface (using the interface_name:n notation) while on other systems (Windows) a single interface will have a list of addresses for each protocol. In both cases there is a protocol list, but it may contain only a single element.

    Here's some netifaces code to play with:

    import netifaces
    
    PROTO = netifaces.AF_INET   # We want only IPv4, for now at least
    
    # Get list of network interfaces
    # Note: Can't filter for 'lo' here because Windows lacks it.
    ifaces = netifaces.interfaces()
    
    # Get all addresses (of all kinds) for each interface
    if_addrs = [netifaces.ifaddresses(iface) for iface in ifaces]
    
    # Filter for the desired address type
    if_inet_addrs = [addr[PROTO] for addr in if_addrs if PROTO in addr]
    
    iface_addrs = [s['addr'] for a in if_inet_addrs for s in a if 'addr' in s]
    # Can filter for '127.0.0.1' here.
    

    The above code doesn't map an address back to its interface name (useful for generating ebtables/iptables rules on the fly). So here's a version that keeps the above information with the interface name in a tuple:

    import netifaces
    
    PROTO = netifaces.AF_INET   # We want only IPv4, for now at least
    
    # Get list of network interfaces
    ifaces = netifaces.interfaces()
    
    # Get addresses for each interface
    if_addrs = [(netifaces.ifaddresses(iface), iface) for iface in ifaces]
    
    # Filter for only IPv4 addresses
    if_inet_addrs = [(tup[0][PROTO], tup[1]) for tup in if_addrs if PROTO in tup[0]]
    
    iface_addrs = [(s['addr'], tup[1]) for tup in if_inet_addrs for s in tup[0] if 'addr' in s]
    

    And, no, I'm not in love with list comprehensions. It's just the way my brain works these days.

    The following snippet will print it all out:

    from __future__ import print_function  # For 2.x folks
    from pprint import pprint as pp
    
    print('\nifaces = ', end='')
    pp(ifaces)
    
    print('\nif_addrs = ', end='')
    pp(if_addrs)
    
    print('\nif_inet_addrs = ', end='')
    pp(if_inet_addrs)
    
    print('\niface_addrs = ', end='')
    pp(iface_addrs)
    

    Enjoy!

    0 讨论(0)
提交回复
热议问题