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


当前回答

[仅限Windows]如果您不想使用外部包,也不想依赖外部Internet服务器,这可能会有所帮助。这是一个代码样本,我在谷歌代码搜索和修改返回所需的信息:

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上工作。

其他回答

在拥有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

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的方式。

这将在大多数linux盒子上工作:

import socket, subprocess, re
def get_ipv4_address():
    """
    Returns IP address(es) of current machine.
    :return:
    """
    p = subprocess.Popen(["ifconfig"], stdout=subprocess.PIPE)
    ifc_resp = p.communicate()
    patt = re.compile(r'inet\s*\w*\S*:\s*(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})')
    resp = patt.findall(ifc_resp[0])
    print resp

get_ipv4_address()

简单而甜蜜!

def getip():

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

    return(ip)

你可以在GNU/Linux上使用命令“ip route”来知道你当前的ip地址。

这显示了运行在路由器/调制解调器上的DHCP服务器给接口的IP地址。通常“192.168.1.1/24”是本地网络的IP地址,其中“24”是DHCP服务器在掩码范围内可能提供的IP地址范围。

这里有一个例子:请注意,PyNotify只是一个补充,以阐明我的观点,根本不是必需的

#! /usr/bin/env python

import sys , pynotify

if sys.version_info[1] != 7:
   raise RuntimeError('Python 2.7 And Above Only')       

from subprocess import check_output # Available on Python 2.7+ | N/A 

IP = check_output(['ip', 'route'])
Split_Result = IP.split()

# print Split_Result[2] # Remove "#" to enable

pynotify.init("image")
notify = pynotify.Notification("Ip", "Server Running At:" + Split_Result[2] , "/home/User/wireless.png")    
notify.show()    

这样做的好处是您不需要指定网络接口。这在运行套接字服务器时非常有用

你可以使用easy_install甚至Pip安装PyNotify:

easy_install py-notify

or

pip install py-notify

或者在python脚本/解释器中

from pip import main

main(['install', 'py-notify'])