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


当前回答

如果计算机有到Internet的路由,即使/etc/hosts没有正确设置,这也将始终工作以获得首选的本地ip地址。

import socket

s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect(('8.8.8.8', 1))  # connect() for UDP doesn't send packets
local_ip_address = s.getsockname()[0]

其他回答

要获取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()

作为别名myip:

alias myip="python -c 'import socket; print([l for l in ([ip for ip in socket.gethostbyname_ex(socket.gethostname())[2] if not ip.startswith(\"127.\")][:1], [[(s.connect((\"8.8.8.8\", 53)), s.getsockname()[0], s.close()) for s in [socket.socket(socket.AF_INET, socket.SOCK_DGRAM)]][0][1]]) if l][0][0])'"

适用于Python 2。3. Python。x,现代和旧的Linux发行版,OSX/macOS和Windows来查找当前的IPv4地址。 对于有多个IP地址、IPv6、没有配置IP地址或没有互联网访问的机器,将不会返回正确的结果。 据报道,这在最新版本的macOS上不起作用。

注意:如果你打算在Python程序中使用类似的东西,正确的方法是使用支持IPv6的Python模块。


与上面相同,但只是Python代码:

import socket
print([l for l in ([ip for ip in socket.gethostbyname_ex(socket.gethostname())[2] if not ip.startswith("127.")][:1], [[(s.connect(('8.8.8.8', 53)), s.getsockname()[0], s.close()) for s in [socket.socket(socket.AF_INET, socket.SOCK_DGRAM)]][0][1]]) if l][0][0])

如果没有配置IP地址,将抛出异常。


也可以在没有互联网连接的局域网上工作的版本:

import socket
print((([ip for ip in socket.gethostbyname_ex(socket.gethostname())[2] if not ip.startswith("127.")] or [[(s.connect(("8.8.8.8", 53)), s.getsockname()[0], s.close()) for s in [socket.socket(socket.AF_INET, socket.SOCK_DGRAM)]][0][1]]) + ["no IP found"])[0])

(谢谢@ccpizza)


背景:

使用socket.gethostbyname(socket.gethostname())在这里不起作用,因为我所在的一台计算机有一个/etc/hosts,其中有重复的条目和对自身的引用。Socket.gethostbyname()只返回/etc/hosts.中的最后一项

这是我最初的尝试,它清除了所有以“127”开头的地址。”:

import socket
print([ip for ip in socket.gethostbyname_ex(socket.gethostname())[2] if not ip.startswith("127.")][:1])

这适用于Python 2和3,在Linux和Windows上,但不能处理多个网络设备或IPv6。然而,它在最近的Linux发行版上停止工作,所以我尝试了这种替代技术。它尝试在53端口8.8.8.8连接谷歌DNS服务器:

import socket
print([(s.connect(('8.8.8.8', 53)), s.getsockname()[0], s.close()) for s in [socket.socket(socket.AF_INET, socket.SOCK_DGRAM)]][0][1])

然后,我将上述两种技术组合成一个应该在任何地方都适用的一行程序,并在这个答案的顶部创建了myip别名和Python代码片段。

随着IPv6的日益普及,对于具有多个网络接口的服务器,使用第三方Python模块查找IP地址可能比这里列出的任何方法都更健壮和可靠。

这与之前发布的答案非常相似,但我找不到任何与这种调用用法有关的答案。这是我用于ipv4的。对于ipv6,更改'。' in to ':' in

import socket
print next(i[4][0] for i in socket.getaddrinfo(
    socket.gethostname(), 80) if '127.' not in i[4][0] and '.' in i[4][0]);"
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。

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