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


当前回答

import netifaces as ni 

ni.ifaddresses('eth0')
ip = ni.ifaddresses('eth0')[ni.AF_INET][0]['addr']
print(ip)

这将返回你的IP地址在Ubuntu系统和MacOS。输出将是系统IP地址,如我的IP: 192.168.1.10。

其他回答

import socket
socket.gethostbyname(socket.gethostname())

这并不总是有效(在/etc/hosts主机名为127.0.0.1的机器上返回127.0.0.1),gimel显示的是一个缓和的方法,使用socket.getfqdn()代替。当然,您的机器需要一个可解析的主机名。

@fatal_error解决方案应该是接受的答案!这是他的解决方案在nodejs中的实现,以备人们需要:

const dgram = require('dgram');

async function get_local_ip() {
    const s = new dgram.createSocket('udp4');
    return new Promise((resolve, reject) => {
        try {
            s.connect(1, '8.8.8.8', function () {
                const ip = s.address();
                s.close();
                resolve(ip.address)
            });
        } catch (e) {
            console.error(e);
            s.close();
            reject(e);
        }
    })
}

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

# imports
import errno
import socket
import logging

# 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:
        # log.info("trapped error connecting to %r via %r", remote, family, exc_info=True)
        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 belongs to host
            return local
    else:
        # NOTE: the two addresses used here are TESTNET addresses,
        #       which should never exist in the real world.
        if ipv6:
            local = _get_local_addr(socket.AF_INET6, "2001:db8::1234")
            # expand zero groups so the startswith() test works.
            if local:
                local = expand_addr(local)
        else:
            local = None
        if not local:
            local = _get_local_addr(socket.AF_INET, "192.0.2.123")
            if not local:
                return None
    if local.startswith(_ignored_networks):
        return None
    return local

通过命令行utils产生“干净”输出的一个简单方法:

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

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

好吧,这是Windows特定的,需要安装python WMI模块,但这似乎比不断尝试调用外部服务器要简单得多。这只是另一种选择,因为已经有很多好的选择,但它可能非常适合您的项目。

Import WMI

def getlocalip():
    local = wmi.WMI()
    for interface in local.Win32_NetworkAdapterConfiguration(IPEnabled=1):
        for ip_address in interface.IPAddress:
            if ip_address != '0.0.0.0':
                localip = ip_address
    return localip







>>>getlocalip()
u'xxx.xxx.xxx.xxx'
>>>

顺便说一下,WMI非常强大……如果你正在做任何窗口机器的远程管理,你一定要看看它能做什么。