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


当前回答

Pyroute2是一个很棒的库,不仅可以用来获取IP地址,还可以用来获取网关信息和其他有用的信息。 下面的代码可以获取任意接口的ipv4地址。

from pyroute2 import IPRoute
ip = IPRoute()

def get_ipv4_address(intf):
    return dict(ip.get_addr(label=intf)[0]['attrs'])['IFA_LOCAL']

print(get_ipv4_address('eth0'))

其他回答

import socket
[i[4][0] for i in socket.getaddrinfo(socket.gethostname(), None)]

Netifaces可通过PIP和easy_install获得。(我知道,它不在基础,但它可能值得安装。)

Netifaces在不同平台上确实有一些奇怪之处:

localhost/loop-back接口可能并不总是包含在内(Cygwin)。 地址按协议列出(例如IPv4, IPv6),协议按接口列出。在某些系统(Linux)上,每个协议-接口对都有自己的关联接口(使用interface_name:n表示法),而在其他系统(Windows)上,单个接口将有每个协议的地址列表。在这两种情况下都有一个协议列表,但它可能只包含一个元素。

下面是一些netifaces代码:

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.

上面的代码没有将地址映射回接口名(对于动态生成ebtables/iptables规则很有用)。所以这里有一个版本,它将上述信息和接口名称保存在一个元组中:

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]

而且,不,我不喜欢列表理解。这些天我的大脑就是这么运转的。

下面的代码段将全部打印出来:

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)

享受吧!

我必须解决“判断一个IP地址是否是本地的”这个问题,我的第一个想法是建立一个本地IP列表,然后与之匹配。这让我想到了这个问题。然而,我后来意识到有一种更直接的方法:尝试绑定该IP,看看它是否有效。

_local_ip_cache = []
_nonlocal_ip_cache = []
def ip_islocal(ip):
    if ip in _local_ip_cache:
        return True
    if ip in _nonlocal_ip_cache:
        return False
    s = socket.socket()
    try:
        try:
            s.bind((ip, 0))
        except socket.error, e:
            if e.args[0] == errno.EADDRNOTAVAIL:
                _nonlocal_ip_cache.append(ip)
                return False
            else:
                raise
    finally:
        s.close()
    _local_ip_cache.append(ip)
    return True

我知道这并不能直接回答问题,但是这对于任何试图解决相关问题的人以及遵循相同思路的人都是有帮助的。我认为这是一个跨平台的解决方案。

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。

一个我不相信已经发布的版本。 我在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'