如何在Python中独立于平台且仅使用标准库找到本地IP地址(即192.168.x.x或10.0.x.x)?
如何在Python中独立于平台且仅使用标准库找到本地IP地址(即192.168.x.x或10.0.x.x)?
对 ninjagecko 答案的改进版本。此方法适用于允许 UDP 广播且不需要访问局域网或互联网上的地址的任何 LAN。
import socket
def getNetworkIp():
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
s.connect(('<broadcast>', 0))
return s.getsockname()[0]
print (getNetworkIp())
<broadcast>
怎么会是一个有效的主机名?!!这种口头主机名中有多少是有效的? - Dev Aggarwal我在我的Ubuntu机器上使用这个:
import commands
commands.getoutput("/sbin/ifconfig").split("\n")[1].split()[1][5:]
这不起作用。
我相信这个版本还没有发布过。 我在Ubuntu 12.04上使用Python 2.7进行了测试。
在此发现解决方案:http://code.activestate.com/recipes/439094-get-the-ip-address-associated-with-a-network-inter/
import socket
import fcntl
import struct
def get_ip_address(ifname):
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
return socket.inet_ntoa(fcntl.ioctl(
s.fileno(),
0x8915, # SIOCGIFADDR
struct.pack('256s', ifname[:15])
)[20:24])
示例结果:
>>> get_ip_address('eth0')
'38.113.228.130'
- cessorsocket.inet_ntoa(fcntl.ioctl(s.fileno(), 0x8915, struct.pack('256s', 'enp0s31f6'[:15].encode('utf-8')))[20:24]) '192.168.1.1'
在 Debian(已测试)以及我怀疑的大多数 Linux 系统上...
import commands
RetMyIP = commands.getoutput("hostname -I")
在 MS Windows 上(已测试)
import socket
socket.gethostbyname(socket.gethostname())
hostname: illegal option -- I\nusage: hostname [-fs] [name-of-host]
。 - Derek 朕會功夫对于Linux系统,您只需像这样使用hostname -I
系统命令的check_output
:
from subprocess import check_output
check_output(['hostname', '-I'])
check_output(['hostname', '-I']).decode().strip()
- iku这是UnkwnTech回答的一个变体 -- 它提供了一个get_local_addr()
函数,该函数返回主机的主要局域网IP地址。我发表这篇文章是因为它添加了许多内容:IPv6支持、错误处理、忽略本地主机/链路本地地址,并使用测试网络地址(RFC5737)进行连接。
# imports
import errno
import socket
import logging
# localhost prefixes
_local_networks = ("127.", "0:0:0:0:0:0:0:1")
# ignore these prefixes -- localhost, unspecified, and link-local
_ignored_networks = _local_networks + ("0.", "0:0:0:0:0:0:0:0", "169.254.", "fe80:")
def detect_family(addr):
if "." in addr:
assert ":" not in addr
return socket.AF_INET
elif ":" in addr:
return socket.AF_INET6
else:
raise ValueError("invalid ipv4/6 address: %r" % addr)
def expand_addr(addr):
"""convert address into canonical expanded form --
no leading zeroes in groups, and for ipv6: lowercase hex, no collapsed groups.
"""
family = detect_family(addr)
addr = socket.inet_ntop(family, socket.inet_pton(family, addr))
if "::" in addr:
count = 8-addr.count(":")
addr = addr.replace("::", (":0" * count) + ":")
if addr.startswith(":"):
addr = "0" + addr
return addr
def _get_local_addr(family, remote):
try:
s = socket.socket(family, socket.SOCK_DGRAM)
try:
s.connect((remote, 9))
return s.getsockname()[0]
finally:
s.close()
except socket.error:
# log.info("trapped error connecting to %r via %r", remote, family, exc_info=True)
return None
def get_local_addr(remote=None, ipv6=True):
"""get LAN address of host
:param remote:
return LAN address that host would use to access that specific remote address.
by default, returns address it would use to access the public internet.
:param ipv6:
by default, attempts to find an ipv6 address first.
if set to False, only checks ipv4.
:returns:
primary LAN address for host, or ``None`` if couldn't be determined.
"""
if remote:
family = detect_family(remote)
local = _get_local_addr(family, remote)
if not local:
return None
if family == socket.AF_INET6:
# expand zero groups so the startswith() test works.
local = expand_addr(local)
if local.startswith(_local_networks):
# border case where remote addr belongs to host
return local
else:
# NOTE: the two addresses used here are TESTNET addresses,
# which should never exist in the real world.
if ipv6:
local = _get_local_addr(socket.AF_INET6, "2001:db8::1234")
# expand zero groups so the startswith() test works.
if local:
local = expand_addr(local)
else:
local = None
if not local:
local = _get_local_addr(socket.AF_INET, "192.0.2.123")
if not local:
return None
if local.startswith(_ignored_networks):
return None
return local
socket.error
可能有助于诊断。 - Eli Collins我可以告诉您,这个方法是可行的:
import socket
addr = socket.gethostbyname(socket.gethostname())
适用于OS X(10.6、10.5)、Windows XP以及经过良好管理的RHEL部门服务器。但是,在我刚刚进行了一些内核修改的极简CentOS虚拟机上无法使用。因此,在这种情况下,您只需检查127.0.0.1地址,并执行以下操作:
if addr == "127.0.0.1":
import commands
output = commands.getoutput("/sbin/ifconfig")
addr = parseaddress(output)
然后从输出中解析出IP地址。需要注意的是,ifconfig默认情况下不在普通用户的PATH路径中,这就是我在命令中给出完整路径的原因。希望这能帮助到您。
通过命令行工具产生“干净”的输出的一种简单方法:
import commands
ips = commands.getoutput("/sbin/ifconfig | grep -i \"inet\" | grep -iv \"inet6\" | " +
"awk {'print $2'} | sed -ne 's/addr\:/ /p'")
print ips
这里有一个适用于Linux的解决方案:获取与网络接口相关联的IP地址。
import socket
[i[4][0] for i in socket.getaddrinfo(socket.gethostname(), None)]
['fe80::34e8:fe19:1459:2cde%22','fe80::d528:99fb:d572:e289%12', '192.168.56.1', '192.168.1.2']
。 - Nakilon
ifconfig -a
命令并使用其输出... - Fredrik Pihlip addr
更加适合(而且更容易解析)。 - phihag