如何找到本地IP地址(即192.168.x。x或10.0.x.x)在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)]

其他回答

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

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

好吧,这是Windows特定的,需要安装python WMI模块,但这似乎比不断尝试调用外部服务器要简单得多。这只是另一种选择,因为已经有很多好的选择,但它可能非常适合您的项目。

Import WMI

def getlocalip():
    local = wmi.WMI()
    for interface in local.Win32_NetworkAdapterConfiguration(IPEnabled=1):
        for ip_address in interface.IPAddress:
            if ip_address != '0.0.0.0':
                localip = ip_address
    return localip







>>>getlocalip()
u'xxx.xxx.xxx.xxx'
>>>

顺便说一下,WMI非常强大……如果你正在做任何窗口机器的远程管理,你一定要看看它能做什么。

import socket
socket.gethostbyname(socket.getfqdn())

另一个变体的前面的答案,可以保存到一个名为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