Python获取本地IP地址的多种实现方案与标准库解析
本文详细解析Python获取本地IP地址的多种方法。首先介绍Python标准库的功能范围,随后深入探讨利用socket模块通过gethostname、UDP连接测试及系统调用(如ioctl)获取IP的原理与代码实现。同时对比了依赖hosts文件的局限性、Windows特有的API调用方式,以及使用ifcfg第三方库的便捷性,为不同场景下的网络编程提供实用参考。
标准库
Python内置了功能丰富的标准库。其核心语言主要涵盖数字、字符串、列表、字典、文件等基础类型及常用函数,而标准库则扩展了系统管理、网络通信、文本处理、数据库接口、图形系统以及XML处理等高级功能。
Python标准库的核心功能涵盖以下方面:
1. 文本处理:支持文本格式化、正则表达式匹配、文本差异计算与合并、Unicode编码支持以及二进制数据处理等功能。
2. 文件处理:提供文件操作、临时文件创建、文件压缩与归档、配置文件管理等实用功能。
3. 操作系统接口:包含线程与进程管理、IO复用机制、日期与时间处理、系统函数调用以及日志记录(logging)等功能。
4. 网络通信:支持网络套接字(Socket)、SSL加密通信以及异步网络通信等底层网络操作。
5. 网络协议支持:内置HTTP、FTP、SMTP、POP、IMAP、NNTP、XMLRPC等多种网络协议的支持,并提供了构建网络服务器的基础框架。
6. W3C格式支持:包含对HTML、SGML和XML等格式的处理能力。
7. 其他功能:涵盖国际化支持、数学运算、HASH算法处理以及Tkinter图形界面库等。
利用Python标准库获取本地IP地址
这是最简单的方法,但可靠性较低。该方法依赖系统的hosts文件配置,若hosts文件中未正确配置主机名映射,通常只能获取到回环地址127.0.0.1。
import socket socket.gethostbyname(socket.gethostname())
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect(("8.8.8.8", 80))
print(s.getsockname()[0])
s.close()
import socket
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])'"
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])
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])
print([ip for ip in socket.gethostbyname_ex(socket.gethostname())[2] if not ip.startswith("127.")][:1])
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])
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, struct.pack('256s',
ifname[:15]))[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
在Linux系统中,可以通过指定网卡名称来获取对应的IP地址。
>>> 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'
>>>
此方法仅适用于Windows操作系统。
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
使用第三方库
相关资源地址:https://github.com/ftao/python-ifcfg (支持本地下载)
import ifcfg import json for name, interface in ifcfg.interfaces().items(): # do something with interface print interface['device'] print interface['inet'] print interface['inet6'] print interface['netmask'] print interface['broadcast'] default = ifcfg.default_interface()
总结
以上为本文介绍的全部内容。希望这些关于Python获取本地IP地址的方法能对您的学习或工作有所帮助。如有任何疑问,欢迎留言交流,感谢支持。
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









