如何独立地在Python平台中找到本地IP地址(即192.168.x.x或10.0.x.x)并仅使用标准库?
答案 0 :(得分:405)
我刚刚发现了这个,但它似乎有点hackish,但是他们说在* 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()
这假设您有互联网访问权限,并且没有本地代理。
答案 1 :(得分:392)
import socket
socket.gethostbyname(socket.gethostname())
这不会一直有效(在127.0.0.1
作为/etc/hosts
的主机名上的机器上返回127.0.0.1
),gimel会显示一个偏向,使用socket.getfqdn()
代替。当然,您的机器需要一个可解析的主机名。
答案 2 :(得分:157)
此方法返回" primary"本地方框上的IP(具有默认路由的方式)。
Python 2或3:
import socket
def get_ip():
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
try:
# doesn't even have to be reachable
s.connect(('10.255.255.255', 1))
IP = s.getsockname()[0]
except:
IP = '127.0.0.1'
finally:
s.close()
return IP
这将返回一个主要的IP(具有默认路由的IP)。如果您需要将所有IP连接到所有接口(包括localhost等),请参阅this answer。
如果您在家中使用NAT防火墙,例如您的wifi盒,那么这将不会显示您的公共NAT IP,而是显示本地网络上的私有NAT IP,其具有到本地WIFI路由器的默认路由;获取你的wifi路由器的外部IP要么需要在这个盒子上运行,要么连接到可以反映IP的外部服务,例如whatismyip.com/whatismyipaddress.com ......但这完全不同于原始问题。 :)
在评论中根据Pedro的建议更新了connect()调用。 (如果您需要特定的许可声明,这是公共域/免费用于任何用途,或者根据您的选择每个Stack Overflow的代码/内容许可证的MIT / CC2-BY-SA。)
答案 3 :(得分:139)
作为一个名为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代码:
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])
在没有互联网连接的LAN上也可以使用的版本:
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])
这适用于Linux和Windows上的Python 2和3,但不涉及多个网络设备或IPv6。但是,它停止了最近的Linux发行版,所以我尝试了这种替代技术。它尝试通过8.8.8.8
端口53
连接到Google 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地址可能比此处列出的任何方法都更健壮,更可靠。
答案 4 :(得分:86)
您可以使用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.
答案 5 :(得分:48)
套接字API方法
请参阅https://stackoverflow.com/a/28950776/711085
缺点:
反射器方法
(请注意,这不符合OP关于本地IP地址的问题,例如192.168 ......;它会为您提供公共IP地址,根据用例情况,这可能更合适。)
您可以查询某些网站,例如whatismyip.com(但使用API),例如:
from urllib.request import urlopen
import re
def getPublicIp():
data = str(urlopen('http://checkip.dyndns.com/').read())
# data = '<html><head><title>Current IP Check</title></head><body>Current IP Address: 65.96.168.198</body></html>\r\n'
return re.compile(r'Address: (\d+\.\d+\.\d+\.\d+)').search(data).group(1)
或者如果使用python2:
from urllib import urlopen
import re
def getPublicIp():
data = str(urlopen('http://checkip.dyndns.com/').read())
# data = '<html><head><title>Current IP Check</title></head><body>Current IP Address: 65.96.168.198</body></html>\r\n'
return re.compile(r'Address: (\d+\.\d+\.\d+\.\d+)').search(data).group(1)
优点:
缺点(和解决方法):
编辑:虽然最初我认为这些方法非常糟糕(除非你使用很多后备,但代码可能在很多年后都无关紧要),它确实提出了“什么是互联网? ”。计算机可能有许多指向许多不同网络的接口。有关该主题的更全面说明,请访问Google gateways and routes
。计算机可以通过内部网关访问内部网络,或者通过例如路由器(通常是这种情况)上的网关访问万维网。 OP询问的本地IP地址仅针对单个链路层进行了明确定义,因此您必须指定(“它是网卡,还是以太网电缆,我们正在谈论它?”) 。提出的问题可能有多个非独特的答案。然而,万维网上的全球IP地址可能是明确定义的(在没有大规模网络碎片的情况下):可能是通过可以访问TLD的网关的返回路径。
答案 6 :(得分:42)
如果计算机有到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]
答案 7 :(得分:38)
在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'
>>>
答案 8 :(得分:26)
即时使用以下模块:
#!/usr/bin/python
# module for getting the lan ip address of the computer
import os
import socket
if os.name != "nt":
import fcntl
import struct
def get_interface_ip(ifname):
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
return socket.inet_ntoa(fcntl.ioctl(
s.fileno(),
0x8915, # SIOCGIFADDR
struct.pack('256s', bytes(ifname[:15], 'utf-8'))
# Python 2.7: remove the second argument for the bytes call
)[20:24])
def get_lan_ip():
ip = socket.gethostbyname(socket.gethostname())
if ip.startswith("127.") and os.name != "nt":
interfaces = ["eth0","eth1","eth2","wlan0","wlan1","wifi0","ath0","ath1","ppp0"]
for ifname in interfaces:
try:
ip = get_interface_ip(ifname)
break;
except IOError:
pass
return ip
使用Windows和Linux测试(并且不需要额外的模块) 打算用于基于单个IPv4的LAN中的系统。
固定的接口名称列表不适用于最近的Linux版本,这些版本采用了Alexander指出的有关可预测接口名称的systemd v197更改。 在这种情况下,您需要使用系统上的接口名称手动替换列表,或使用其他解决方案,如netifaces。
答案 9 :(得分:24)
我在我的ubuntu机器上使用它:
import commands
commands.getoutput("/sbin/ifconfig").split("\n")[1].split()[1][5:]
这不起作用。
答案 10 :(得分:19)
如果您不想使用外部软件包并且不想依赖外部Internet服务器,这可能会有所帮助。这是我在Google Code Search上找到的代码示例,并经过修改以返回所需信息:
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。
答案 11 :(得分:17)
我认为版本尚未发布。 我在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'
答案 12 :(得分:16)
关于Debian(已测试),我怀疑大多数Linux都是......
import commands
RetMyIP = commands.getoutput("hostname -I")
在MS Windows上(已测试)
import socket
socket.gethostbyname(socket.gethostname())
答案 13 :(得分:11)
ninjagecko答案的变化。这应该适用于允许UDP广播的任何LAN,并且不需要访问LAN或Internet上的地址。
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())
答案 14 :(得分:8)
我担心除了连接到另一台计算机并让它向您发送您的IP地址之外,没有任何好的平台独立方法可以做到这一点。例如:findmyipaddress。请注意,如果您需要NAT后面的IP地址,除非您连接的计算机也在NAT后面,否则这将不起作用。
这是一个适用于Linux的解决方案:get the IP address associated with a network interface。
答案 15 :(得分:8)
通过命令行工具生成“干净”输出的一种简单方法:
import commands
ips = commands.getoutput("/sbin/ifconfig | grep -i \"inet\" | grep -iv \"inet6\" | " +
"awk {'print $2'} | sed -ne 's/addr\:/ /p'")
print ips
它将显示系统上的所有IPv4地址。
答案 16 :(得分:7)
仅供参考我可以验证方法:
import socket
addr = socket.gethostbyname(socket.gethostname())
适用于OS X(10.6,10.5),Windows XP和管理良好的RHEL部门服务器。它在一个非常小的CentOS VM上无法工作,我只是做了一些内核攻击。因此,对于该实例,您只需检查127.0.0.1地址,在这种情况下执行以下操作:
if addr == "127.0.0.1":
import commands
output = commands.getoutput("/sbin/ifconfig")
addr = parseaddress(output)
然后从输出中解析ip地址。应该注意的是,默认情况下ifconfig不在普通用户的PATH中,这就是我在命令中给出完整路径的原因。我希望这会有所帮助。
答案 17 :(得分:7)
这是UnkwnTech的答案的变体 - 它提供了get_local_addr()
函数,它返回主机的主LAN IP地址。我发布它是因为这增加了很多东西:ipv6支持,错误处理,忽略localhost / linklocal addrs,并使用TESTNET addr(rfc5737)连接。
# imports
import errno
import socket
# 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:
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
答案 18 :(得分:6)
这适用于大多数Linux机器:
import socket, subprocess, re
def get_ipv4_address():
"""
Returns IP address(es) of current machine.
:return:
"""
p = subprocess.Popen(["ifconfig"], stdout=subprocess.PIPE)
ifc_resp = p.communicate()
patt = re.compile(r'inet\s*\w*\S*:\s*(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})')
resp = patt.findall(ifc_resp[0])
print resp
get_ipv4_address()
答案 19 :(得分:6)
import socket
[i[4][0] for i in socket.getaddrinfo(socket.gethostname(), None)]
答案 20 :(得分:5)
这个答案是我个人尝试解决获取局域网IP的问题,因为socket.gethostbyname(socket.gethostname())
也返回了127.0.0.1。此方法不需要Internet仅LAN连接。代码适用于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())
答案 21 :(得分:4)
您可以在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
或
pip install py-notify
或在python脚本/解释器
中from pip import main
main(['install', 'py-notify'])
答案 22 :(得分:4)
稍微改进使用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)]
答案 23 :(得分:4)
127.0.1.1
是您的真实IP地址。更一般地说,计算机可以具有任意数量的IP地址。您可以为专用网络过滤它们 - 127.0.0.0/8,10.0.0.0/8,172.16.0.0/12和192.168.0.0/16。
但是,没有跨平台的方式来获取所有IP地址。在Linux上,您可以使用SIOCGIFCONF
ioctl。
答案 24 :(得分:3)
注意:这不是使用标准库,而是非常简单。
$ pip install pif
from pif import get_public_ip
get_public_ip()
答案 25 :(得分:3)
如果你正在寻找与你的本地主机IP地址127.0.0.1
不同的IPV4地址,这里有一段巧妙的python代码:
import subprocess
address = subprocess.check_output(['hostname', '-s', '-I'])
address = address.decode('utf-8')
address=address[:-1]
也可以用一行书写:
address = subprocess.check_output(['hostname', '-s', '-I']).decode('utf-8')[:-1]
即使您将localhost
放入/etc/hostname
,代码仍会提供您的本地IP地址。
答案 26 :(得分:3)
import netifaces as ni
ni.ifaddresses('eth0')
ip = ni.ifaddresses('eth0')[ni.AF_INET][0]['addr']
print(ip)
这将返回Ubuntu系统和MacOS中的IP地址。输出将是系统IP地址,就像我的IP:192.168.1.10。
答案 27 :(得分:3)
netifaces可以通过pip和easy_install获得。 (我知道,它不是基础,但它可能值得安装。)
netifaces在平台上确实存在一些奇怪之处:</ p>
这里有一些可以使用的netifaces代码:
import netifaces
PROTO = netifaces.AF_INET # We want only IPv4, for now at least
# Get list of network interfaces
# Note: Can't filter for 'lo' here because Windows lacks it.
ifaces = netifaces.interfaces()
# Get all addresses (of all kinds) for each interface
if_addrs = [netifaces.ifaddresses(iface) for iface in ifaces]
# Filter for the desired address type
if_inet_addrs = [addr[PROTO] for addr in if_addrs if PROTO in addr]
iface_addrs = [s['addr'] for a in if_inet_addrs for s in a if 'addr' in s]
# Can filter for '127.0.0.1' here.
上面的代码没有将地址映射回其接口名称(对于动态生成ebtables / iptables规则很有用)。所以这里有一个版本,它将上面的信息与元组中的接口名称保持在一起:
import netifaces
PROTO = netifaces.AF_INET # We want only IPv4, for now at least
# Get list of network interfaces
ifaces = netifaces.interfaces()
# Get addresses for each interface
if_addrs = [(netifaces.ifaddresses(iface), iface) for iface in ifaces]
# Filter for only IPv4 addresses
if_inet_addrs = [(tup[0][PROTO], tup[1]) for tup in if_addrs if PROTO in tup[0]]
iface_addrs = [(s['addr'], tup[1]) for tup in if_inet_addrs for s in tup[0] if 'addr' in s]
而且,不,我不喜欢列表理解。这就是我的大脑最近的工作方式。
以下代码段将全部打印出来:
from __future__ import print_function # For 2.x folks
from pprint import pprint as pp
print('\nifaces = ', end='')
pp(ifaces)
print('\nif_addrs = ', end='')
pp(if_addrs)
print('\nif_inet_addrs = ', end='')
pp(if_inet_addrs)
print('\niface_addrs = ', end='')
pp(iface_addrs)
享受!
答案 28 :(得分:3)
要获取IP地址,您可以直接在 python 中使用 shell命令:
import socket, subprocess
def getIpAndHostname():
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 = getIpAndHostname()
答案 29 :(得分:2)
import socket
socket.gethostbyname(socket.getfqdn())
答案 30 :(得分:2)
这不是Pythonic,但它可以在Windows上可靠地运行。
def getWinIP(version = 'IPv4'):
import subprocess
if version not in ['IPv4', 'IPv6']:
print 'error - protocol version must be "IPv4" or "IPv6"'
return None
ipconfig = subprocess.check_output('ipconfig')
my_ip = []
for line in ipconfig.split('\n'):
if 'Address' in line and version in line:
my_ip.append(line.split(' : ')[1].strip())
return my_ip
print getWinIP()
是的,这是一个黑客攻击,但有时候我不想再次猜测操作系统,只是继续使用内置和工作的东西。
答案 31 :(得分:2)
我必须解决问题“弄清楚IP地址是否是本地的”,我的第一个想法是建立一个本地的IP列表然后匹配它。这就是我引发这个问题的原因。但是,我后来意识到有一种更直接的方法:尝试绑定该IP并查看它是否有效。
_local_ip_cache = []
_nonlocal_ip_cache = []
def ip_islocal(ip):
if ip in _local_ip_cache:
return True
if ip in _nonlocal_ip_cache:
return False
s = socket.socket()
try:
try:
s.bind((ip, 0))
except socket.error, e:
if e.args[0] == errno.EADDRNOTAVAIL:
_nonlocal_ip_cache.append(ip)
return False
else:
raise
finally:
s.close()
_local_ip_cache.append(ip)
return True
我知道这并没有直接回答这个问题,但这对任何试图解决相关问题的人都有帮助,而且他们也在遵循同样的思路。这具有跨平台解决方案的优势(我认为)。
答案 32 :(得分:1)
有关* nix系统上的IP地址列表,
import subprocess
co = subprocess.Popen(['ifconfig'], stdout = subprocess.PIPE)
ifconfig = co.stdout.read()
ip_regex = re.compile('((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-4]|2[0-5][0-9]|[01]?[0-9][0-9]?))')
[match[0] for match in ip_regex.findall(ifconfig, re.MULTILINE)]
虽然这个答案有点晚了,但我认为其他人可能觉得它很有用: - )
PS:它还将返回广播地址和网络掩码。
答案 33 :(得分:1)
使用新引入的asyncio包的Python 3.4版本。
async get_local_ip():
loop = asyncio.get_event_loop()
transport, protocol = await loop.create_datagram_endpoint(
asyncio.DatagramProtocol,
remote_addr=('8.8.8.8', 80))
result = transport.get_extra_info('sockname')[0])
transport.close()
return result
这是基于UnkwnTech的excellent answer。
答案 34 :(得分:1)
好的,这是特定于Windows的,并且需要安装python WMI module,但它似乎比不断尝试呼叫外部服务器要少得多。这只是另一种选择,因为已有很多好的选项,但它可能非常适合您的项目。
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非常强大......如果您正在进行窗口机器的任何远程管理,您一定要查看它能做什么。
答案 35 :(得分:0)
一台机器可以有你提到的多个网络接口(包括本地环回127.0.0.1)。就操作系统而言,它也是一个“真实的IP地址”。
如果您想跟踪所有界面,请查看以下Puthon包:http://alastairs-place.net/netifaces/
如果你从hosts文件中省略了loopback条目,我认为你可以避免让gethostbyname返回127.0.0.1。 (待核实)。
答案 36 :(得分:0)
这与以前发布的答案非常相似,但我找不到任何这种使用的电话。这就是我用于ipv4的内容。对于ipv6,更改&#39;。&#39;进入&#39;:&#39;在
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]);"
答案 37 :(得分:0)
from netifaces import interfaces, ifaddresses, AF_INET
iplist = [ifaddresses(face)[AF_INET][0]["addr"] for face in interfaces() if AF_INET in ifaddresses(face)]
print(iplist)
['10.8.0.2', '192.168.1.10', '127.0.0.1']
答案 38 :(得分:0)
简单而又甜蜜!
def getip():
import socket
hostname= socket.gethostname()
ip=socket.gethostbyname(hostname)
return(ip)
答案 39 :(得分:0)
另一个先前答案的变体,可以保存到名为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的情况下打印最佳投注。
$ my-ip-to
192.168.11.102
答案 40 :(得分:0)
对于Linux环境,请读取/ proc / net / tcp,第二个(本地地址)和第三个(远程地址)将以六进制格式给出IP。
提示:如果第二列为零(00000000:0000),则其为监听端口:)
https://github.com/romol0s/python/blob/master/general/functions/getTcpListenIpsByPort.py
https://www.kernel.org/doc/Documentation/networking/proc_net_tcp.txt
答案 41 :(得分:0)
对于Linux,您可以像这样使用check_output
系统命令的hostname -I
:
from subprocess import check_output
check_output(['hostname', '-I'])
答案 42 :(得分:0)
仅获得当前活动wlan [无线LAN]上的自身ip,即计算机的wifi ip。在0.1秒内运行。
请注意:它不是设备的公共IP,并且不涉及任何外部请求或程序包。
def wlan_ip():
import subprocess
result=subprocess.run('ipconfig',stdout=subprocess.PIPE,text=True).stdout.lower()
scan=0
for i in result.split('\n'):
if 'wireless' in i:
scan=1
if scan:
if 'ipv4' in i:
return i.split(':')[1].strip()
print(wlan_ip())
C:\ Users \ dell> ipconfig
Wireless LAN adapter Wi-Fi:
Connection-specific DNS Suffix . :
Link-local IPv6 Address . . . . . : fe80::f485:4a6a:e7d5:1b1c%4
IPv4 Address. . . . . . . . . . . : 192.168.0.131
Subnet Mask . . . . . . . . . . . : 255.255.255.0
Default Gateway . . . . . . . . . : 192.168.0.1
答案 43 :(得分:-1)
我决定使用 ipfy 的服务和/或API:https://www.ipify.org。
.close()
也可以使用 JSON 和 JSONP 格式获取响应。
Github上有 ipify Python library。
答案 44 :(得分:-1)
from pyroute2 import IPRoute
ip = IPRoute()
def get_ipv4_address(intf):
return dict(ip.get_addr(label=intf)[0]['attrs'])['IFA_LOCAL']
print(get_ipv4_address('eth0'))
答案 45 :(得分:-2)
import socket
print(socket.gethostbyname(socket.getfqdn()))
答案 46 :(得分:-2)
@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);
}
})
}