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


当前回答

我决定使用ipfy: https://www.ipify.org的服务和/或API。

#!/usr/bin/env python3
from urllib.request import urlopen


def public_ip():
    data = urlopen('https://api.ipify.org').read()
    return str(data, encoding='utf-8')


print(public_ip())

还可以以JSON和JSONP格式获得响应。

Github上有一个ipify Python库。

其他回答

稍微改进了使用IP命令的命令版本,并返回IPv4和IPv6地址:

import commands,re,socket

#A generator that returns stripped lines of output from "ip address show"
iplines=(line.strip() for line in commands.getoutput("ip address show").split('\n'))

#Turn that into a list of IPv4 and IPv6 address/mask strings
addresses1=reduce(lambda a,v:a+v,(re.findall(r"inet ([\d.]+/\d+)",line)+re.findall(r"inet6 ([\:\da-f]+/\d+)",line) for line in iplines))
#addresses1 now looks like ['127.0.0.1/8', '::1/128', '10.160.114.60/23', 'fe80::1031:3fff:fe00:6dce/64']

#Get a list of IPv4 addresses as (IPstring,subnetsize) tuples
ipv4s=[(ip,int(subnet)) for ip,subnet in (addr.split('/') for addr in addresses1 if '.' in addr)]
#ipv4s now looks like [('127.0.0.1', 8), ('10.160.114.60', 23)]

#Get IPv6 addresses
ipv6s=[(ip,int(subnet)) for ip,subnet in (addr.split('/') for addr in addresses1 if ':' in addr)]

@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);
        }
    })
}

另一个变体的前面的答案,可以保存到一个名为my-ip-to的可执行脚本:

#!/usr/bin/env python

import sys, socket

if len(sys.argv) > 1:
    for remote_host in sys.argv[1:]:
        # determine local host ip by outgoing test to another host
        # use port 9 (discard protocol - RFC 863) over UDP4
        with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s:
            s.connect((remote_host, 9))
            my_ip = s.getsockname()[0]
            print(my_ip, flush=True)
else:
    import platform

    my_name = platform.node()
    my_ip = socket.gethostbyname(my_name)
    print(my_ip)

它需要任意数量的远程主机,并打印出本地ip,逐个到达它们:

$ my-ip-to z.cn g.cn localhost
192.168.11.102
192.168.11.102
127.0.0.1
$

并在没有给出arg时打印best-bet。

$ my-ip-to
192.168.11.102

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'))

Windows解决方案,要么接受,要么放弃。

在当前活动的无线局域网[无线局域网]上,即计算机的ip地址(wifi路由器或网络交换机)。

注意:它不是设备的公共IP,不涉及任何外部请求、包和公共api。

核心思想是解析shell命令:ipconfig或linux上的ifconfig的输出。我们使用子进程来获取输出。

def wlan_ip():
    import subprocess
    result=subprocess.run('ipconfig',stdout=subprocess.PIPE,text=True).stdout.lower()
    scan=0
    for i in result.split('\n'):
        if 'wireless' in i: #use "wireless" or wireless adapters and "ethernet" for wired connections
            scan=1
        if scan:
            if 'ipv4' in i:
                return i.split(':')[1].strip()
print(wlan_ip())

这是在CMD:'ipconfig'后发生的事情:

我们得到这个输出,我们在python中使用subprocess output捕获它。

C:\Users\戴尔> ipconfig

Wireless LAN adapter Wi-Fi:

   Connection-specific DNS Suffix  . :
   Link-local IPv6 Address . . . . . : fe80::f485:4a6a:e7d5:1b1c%4
   IPv4 Address. . . . . . . . . . . : 192.168.0.131
   Subnet Mask . . . . . . . . . . . : 255.255.255.0
   Default Gateway . . . . . . . . . : 192.168.0.1

我们用python语言解析了字符串,以选择当前网络上无线适配器的IP的方式。