使用Python的stdlib查找本地IP地址

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用Python的stdlib查找本地IP地址相关的知识,希望对你有一定的参考价值。

如何在Python平台中独立地找到本地IP地址(即192.168.x.x或10.0.x.x)并仅使用标准库?

答案
import socket
socket.gethostbyname(socket.gethostname())

这总是不起作用(在127.0.0.1中将主机名称为/etc/hosts的机器上返回127.0.0.1),gimel显示的是paliative,使用socket.getfqdn()代替。当然,您的机器需要可解析的主机名。

另一答案

我在我的ubuntu机器上使用它:

import commands
commands.getoutput("/sbin/ifconfig").split("
")[1].split()[1][5:]

这不起作用。

另一答案

如果您不想使用外部程序包并且不想依赖外部Internet服务器,这可能会有所帮助。这是我在Google Code Search上找到的代码示例,并经过修改以返回所需信息:

def getIPAddresses():
    from ctypes import Structure, windll, sizeof
    from ctypes import POINTER, byref
    from ctypes import c_ulong, c_uint, c_ubyte, c_char
    MAX_ADAPTER_DESCRIPTION_LENGTH = 128
    MAX_ADAPTER_NAME_LENGTH = 256
    MAX_ADAPTER_ADDRESS_LENGTH = 8
    class IP_ADDR_STRING(Structure):
        pass
    LP_IP_ADDR_STRING = POINTER(IP_ADDR_STRING)
    IP_ADDR_STRING._fields_ = [
        ("next", LP_IP_ADDR_STRING),
        ("ipAddress", c_char * 16),
        ("ipMask", c_char * 16),
        ("context", c_ulong)]
    class IP_ADAPTER_INFO (Structure):
        pass
    LP_IP_ADAPTER_INFO = POINTER(IP_ADAPTER_INFO)
    IP_ADAPTER_INFO._fields_ = [
        ("next", LP_IP_ADAPTER_INFO),
        ("comboIndex", c_ulong),
        ("adapterName", c_char * (MAX_ADAPTER_NAME_LENGTH + 4)),
        ("description", c_char * (MAX_ADAPTER_DESCRIPTION_LENGTH + 4)),
        ("addressLength", c_uint),
        ("address", c_ubyte * MAX_ADAPTER_ADDRESS_LENGTH),
        ("index", c_ulong),
        ("type", c_uint),
        ("dhcpEnabled", c_uint),
        ("currentIpAddress", LP_IP_ADDR_STRING),
        ("ipAddressList", IP_ADDR_STRING),
        ("gatewayList", IP_ADDR_STRING),
        ("dhcpServer", IP_ADDR_STRING),
        ("haveWins", c_uint),
        ("primaryWinsServer", IP_ADDR_STRING),
        ("secondaryWinsServer", IP_ADDR_STRING),
        ("leaseObtained", c_ulong),
        ("leaseExpires", c_ulong)]
    GetAdaptersInfo = windll.iphlpapi.GetAdaptersInfo
    GetAdaptersInfo.restype = c_ulong
    GetAdaptersInfo.argtypes = [LP_IP_ADAPTER_INFO, POINTER(c_ulong)]
    adapterList = (IP_ADAPTER_INFO * 10)()
    buflen = c_ulong(sizeof(adapterList))
    rc = GetAdaptersInfo(byref(adapterList[0]), byref(buflen))
    if rc == 0:
        for a in adapterList:
            adNode = a.ipAddressList
            while True:
                ipAddr = adNode.ipAddress
                if ipAddr:
                    yield ipAddr
                adNode = adNode.next
                if not adNode:
                    break

用法:

>>> for addr in getIPAddresses():
>>>    print addr
192.168.0.100
10.5.9.207

由于它依赖于windll,因此仅适用于Windows。

另一答案

我认为这个版本尚未发布。我在Ubuntu 12.04上使用python 2.7进行了测试。

在以下网站找到了这个解决方案:http://code.activestate.com/recipes/439094-get-the-ip-address-associated-with-a-network-inter/

import socket
import fcntl
import struct

def get_ip_address(ifname):
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    return socket.inet_ntoa(fcntl.ioctl(
        s.fileno(),
        0x8915,  # SIOCGIFADDR
        struct.pack('256s', ifname[:15])
    )[20:24])

结果示例:

>>> get_ip_address('eth0')
'38.113.228.130'
另一答案

关于Debian(测试),我怀疑大多数Linux的..

import commands

RetMyIP = commands.getoutput("hostname -I")

在MS Windows上(已测试)

import socket

socket.gethostbyname(socket.gethostname())
另一答案

ninjagecko答案的变化。这应该适用于允许UDP广播的任何LAN,并且不需要访问LAN或Internet上的地址。

import socket
def getNetworkIp():
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
    s.connect(('<broadcast>', 0))
    return s.getsockname()[0]

print (getNetworkIp())
另一答案

我担心除了连接到另一台计算机并让它向您发送您的IP地址之外,没有任何好的平台独立方法可以做到这一点。例如:findmyipaddress。请注意,如果您需要NAT后面的IP地址,除非您连接的计算机也在NAT后面,否则这将不起作用。

这是一个适用于Linux的解决方案:get the IP address associated with a network interface

另一答案

通过命令行工具生成“干净”输出的一种简单方法:

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

它将显示系统上的所有IPv4地址。

另一答案

仅供参考我可以验证方法:

import socket
addr = socket.gethostbyname(socket.gethostname())

适用于OS X(10.6,10.5),Windows XP和管理良好的RHEL部门服务器。它在一个非常小的CentOS VM上无法工作,我只是做了一些内核攻击。因此,对于该实例,您只需检查127.0.0.1地址,在这种情况下执行以下操作:

if addr == "127.0.0.1":
     import commands
     output = commands.getoutput("/sbin/ifconfig")
     addr = parseaddress(output)

然后从输出中解析ip地址。应该注意的是,默认情况下ifconfig不在普通用户的PATH中,这就是我在命令中给出完整路径的原因。我希望这有帮助。

另一答案

这是UnkwnTech的答案的变体 - 它提供了get_local_addr()函数,它返回主机的主LAN地址。我发布它是因为这增加了许多东西:ipv6支持,错误处理,忽略localhost / linklocal addrs,并使用TESTNET addr(rfc5737)连接。

# imports
import errno
import socket

# localhost prefixes
_local_networks = ("127.", "0:0:0:0:0:0:0:1")

# ignore these prefixes -- localhost, unspecified, and link-local
_ignored_networks = _local_networks + ("0.", "0:0:0:0:0:0:0:0", "169.254.", "fe80:")

def detect_family(addr):
    if "." in addr:
        assert ":" not in addr
        return socket.AF_INET
    elif ":" in addr:
        return socket.AF_INET6
    else:
        raise ValueError("invalid ipv4/6 address: %r" % addr)

def expand_addr(addr):
    """convert address into canonical expanded form --
    no leading zeroes in groups, and for ipv6: lowercase hex, no collapsed groups.
    """
    family = detect_family(addr)
    addr = socket.inet_ntop(family, socket.inet_pton(family, addr))
    if "::" in addr:
        count = 8-addr.count(":")
        addr = addr.replace("::", (":0" * count) + ":")
        if addr.startswith(":"):
            addr = "0" + addr
    return addr

def _get_local_addr(family, remote):
    try:
        s = socket.socket(family, socket.SOCK_DGRAM)
        try:
            s.connect((remote, 9))
            return s.getsockname()[0]
        finally:
            s.close()
    except socket.error:
        return None

def get_local_addr(remote=None, ipv6=True):
    """get LAN address of host

    :param remote:
        return  LAN address that host would use to access that specific remote address.
        by default, returns address it would use to access the public internet.

    :param ipv6:
        by default, attempts to find an ipv6 address first.
        if set to False, only checks ipv4.

    :returns:
        primary LAN address for host, or ``None`` if couldn't be determined.
    """
    if remote:
        family = detect_family(remote)
        local = _get_local_addr(family, remote)
        if not local:
            return None
        if family == socket.AF_INET6:
            # expand zero groups so the startswith() test works.
            local = expand_addr(local)
        if local.startswith(_local_networks):
            # border case where remote addr bel

以上是关于使用Python的stdlib查找本地IP地址的主要内容,如果未能解决你的问题,请参考以下文章

查找本地网络中的所有 IP 地址

如何获取本地IP地址python?

C# - 查找我机器的本地 IP 地址而不是 VM 的

C# - 查找我机器的本地 IP 地址而不是 VM 的

如何在不使用外部主机的情况下以编程方式查找设备的外部 IP 地址?

获取本地设备的主机名和ip地址