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


当前回答

简单而甜蜜!

def getip():

    import socket
    hostname= socket.gethostname()
    ip=socket.gethostbyname(hostname)

    return(ip)

其他回答

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

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

在拥有iproute2实用程序的现代*NIX系统上,您可以通过subprocess.run()调用它,因为您可以使用-j开关在JSON中输出,然后使用JSON .loads()模块和方法将其转换为python数据结构。下面的代码显示第一个非环回IP地址。

import subprocess
import json

ip = json.loads(subprocess.run('ip -j a'.split(),capture_output=True).stdout.decode())[1]['addr_info'][0]['local'] 

print(ip)

或者,如果你有多个IP,并且想要找到连接到特定目的地的IP,你可以使用IP -j route get 8.8.8.8,如下所示:

import subprocess 
import json 

ip = json.loads(subprocess.run('ip -j route get 8.8.8.8'.split(),capture_output=True).stdout.decode())[0]['prefsrc']

print(ip)

如果你在寻找所有的IP地址,你可以遍历IP -j a返回的字典列表

import subprocess
import json

list_of_dicts = json.loads(subprocess.run('ip -j a'.split(),capture_output=True).stdout.decode())

for interface in list_of_dicts:
    try:print(f"Interface: {interface['ifname']:10} IP: {interface['addr_info'][0]['local']}")
    except:pass

我必须解决“判断一个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

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

我使用以下模块:

#!/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

测试与windows和linux(和不需要额外的模块为那些) 用于在一个基于IPv4的局域网中的系统。

固定的接口名称列表不适用于最近的linux版本,这些版本已经采用了systemd v197关于可预测接口名称的更改,正如Alexander指出的那样。 在这种情况下,您需要手动使用系统上的接口名称替换该列表,或者使用其他解决方案,如netifaces。

如果你正在寻找与本地主机IP地址127.0.0.1不同的IPV4地址,这里有一段简洁的python代码:

import subprocess
address = subprocess.check_output(['hostname', '-s', '-I'])
address = address.decode('utf-8') 
address=address[:-1]

也可以写成一行:

address = subprocess.check_output(['hostname', '-s', '-I']).decode('utf-8')[:-1]

即使您将localhost放在/etc/hostname中,代码仍然会给出本地IP地址。