如何找到本地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上工作。

其他回答

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()代替。当然,您的机器需要一个可解析的主机名。

此方法返回本地盒子上的“主”IP(具有默认路由的IP)。

不需要可路由的网络访问或任何连接。 即使所有接口都从网络断开,也能正常工作。 不需要甚至不尝试去其他地方。 工作与NAT,公共,私有,外部和内部IP 没有外部依赖的纯Python 2(或3)。 支持Linux、Windows和OSX。

Python 3或2:

    import socket
    def get_ip():
        s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        s.settimeout(0)
        try:
            # doesn't even have to be reachable
            s.connect(('10.254.254.254', 1))
            IP = s.getsockname()[0]
        except Exception:
            IP = '127.0.0.1'
        finally:
            s.close()
        return IP
    print(get_ip())

这将返回一个主IP(具有默认路由的IP)。如果您需要将所有IP附加到所有接口(包括localhost等),请参见类似这样的回答。

如果你在一个NAT防火墙后面,比如你家里的wifi路由器,那么这将不会显示你的公共NAT IP,而是显示你在本地网络上的私有IP,它有一个默认路由到你的本地wifi路由器。如果你需要外部IP:

在那个外部设备(wifi路由器)上运行这个功能,或者 连接到外部服务(如https://www.ipify.org/),可以反射从外部世界看到的IP

... 但这些想法与最初的问题完全不同。:)

你可以使用netifaces模块。类型:

pip install netifaces

在你的命令shell中,它会在默认的Python安装中安装自己。

然后你可以这样使用它:

from netifaces import interfaces, ifaddresses, AF_INET
for ifaceName in interfaces():
    addresses = [i['addr'] for i in ifaddresses(ifaceName).setdefault(AF_INET, [{'addr':'No IP addr'}] )]
    print '%s: %s' % (ifaceName, ', '.join(addresses))

在我的电脑上,它打印出:

{45639BDC-1050-46E0-9BE9-075C30DE1FBC}: 192.168.0.100
{D43A468B-F3AE-4BF9-9391-4863A4500583}: 10.5.9.207

这个模块的作者声称它应该在Windows、UNIX和Mac OS X上工作。

你可以在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'])