如何找到本地IP地址(即192.168.x。x或10.0.x.x)在Python平台独立,只使用标准库?
当前回答
@fatal_error解决方案应该是接受的答案!这是他的解决方案在nodejs中的实现,以备人们需要:
const dgram = require('dgram');
async function get_local_ip() {
const s = new dgram.createSocket('udp4');
return new Promise((resolve, reject) => {
try {
s.connect(1, '8.8.8.8', function () {
const ip = s.address();
s.close();
resolve(ip.address)
});
} catch (e) {
console.error(e);
s.close();
reject(e);
}
})
}
其他回答
在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'
>>>
这个答案是我个人试图解决获得LAN IP的问题,因为socket.gethostbyname(socket.gethostname())也返回127.0.0.1。这种方法不需要Internet,只需要一个局域网连接。代码是为Python 3编写的。X但是可以很容易地转换为2.x。使用UDP广播:
import select
import socket
import threading
from queue import Queue, Empty
def get_local_ip():
def udp_listening_server():
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind(('<broadcast>', 8888))
s.setblocking(0)
while True:
result = select.select([s],[],[])
msg, address = result[0][0].recvfrom(1024)
msg = str(msg, 'UTF-8')
if msg == 'What is my LAN IP address?':
break
queue.put(address)
queue = Queue()
thread = threading.Thread(target=udp_listening_server)
thread.queue = queue
thread.start()
s2 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s2.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
waiting = True
while waiting:
s2.sendto(bytes('What is my LAN IP address?', 'UTF-8'), ('<broadcast>', 8888))
try:
address = queue.get(False)
except Empty:
pass
else:
waiting = False
return address[0]
if __name__ == '__main__':
print(get_local_ip())
如果计算机有到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]
作为别名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地址可能比这里列出的任何方法都更健壮和可靠。
对于linux,你可以使用hostname -I system命令的check_output,就像这样:
from subprocess import check_output
check_output(['hostname', '-I'])
推荐文章
- 证书验证失败:无法获得本地颁发者证书
- 当使用pip3安装包时,“Python中的ssl模块不可用”
- 无法切换Python与pyenv
- Python if not == vs if !=
- 如何从scikit-learn决策树中提取决策规则?
- 为什么在Mac OS X v10.9 (Mavericks)的终端中apt-get功能不起作用?
- 将旋转的xtick标签与各自的xtick对齐
- 为什么元组可以包含可变项?
- 如何合并字典的字典?
- 如何创建类属性?
- 不区分大小写的“in”
- 在Python中获取迭代器中的元素个数
- 解析日期字符串并更改格式
- 使用try和。Python中的if
- 如何在Python中获得所有直接子目录