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


当前回答

此方法返回本地盒子上的“主”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

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

其他回答

在Linux上:

>>> import socket, struct, fcntl
>>> sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
>>> sockfd = sock.fileno()
>>> SIOCGIFADDR = 0x8915
>>>
>>> def get_ip(iface = 'eth0'):
...     ifreq = struct.pack('16sH14s', iface, socket.AF_INET, '\x00'*14)
...     try:
...         res = fcntl.ioctl(sockfd, SIOCGIFADDR, ifreq)
...     except:
...         return None
...     ip = struct.unpack('16sH2x4s8x', res)[2]
...     return socket.inet_ntoa(ip)
... 
>>> get_ip('eth0')
'10.80.40.234'
>>> 

你可以使用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上工作。

我刚发现这个,但它似乎有点hack,然而他们说尝试它在*nix和我在windows上,它工作。

import socket
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect(("8.8.8.8", 80))
print(s.getsockname()[0])
s.close()

这假设您有internet访问,并且没有本地代理。

要获取ip地址,可以直接在python中使用shell命令:

import socket, subprocess

def get_ip_and_hostname():
    hostname =  socket.gethostname()

    shell_cmd = "ifconfig | awk '/inet addr/{print substr($2,6)}'"
    proc = subprocess.Popen([shell_cmd], stdout=subprocess.PIPE, shell=True)
    (out, err) = proc.communicate()

    ip_list = out.split('\n')
    ip = ip_list[0]

    for _ip in ip_list:
        try:
            if _ip != "127.0.0.1" and _ip.split(".")[3] != "1":
                ip = _ip
        except:
            pass
    return ip, hostname

ip_addr, hostname = get_ip_and_hostname()

我决定使用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库。