Python跨平台获取网卡信息的实现与应用

发布时间:2026/7/28 5:46:30

Python跨平台获取网卡信息的实现与应用 1. 项目概述Python获取网卡信息的实用场景在日常开发中获取本机网卡信息是个看似简单却经常遇到的需求。比如最近我需要写一个自动化运维工具需要自动识别服务器上的所有网络接口并检查其配置状态。刚开始我以为用简单的ifconfig或ipconfig命令就能解决但实际需求往往更复杂——需要同时获取IPv4/IPv6地址、MAC地址、接口状态等信息并且要跨平台兼容Windows、Linux和macOS。Python作为自动化脚本的首选语言完全能满足这个需求。通过标准库和少量第三方库我们可以用不到50行代码实现一个健壮的网卡信息采集工具。这个工具可以用于服务器自动化运维检查网络设备管理后台本地开发环境配置检查网络故障排查辅助工具注意本文方法仅获取本地网卡信息不涉及任何网络探测或远程主机信息收集符合安全规范。2. 核心实现方案对比2.1 方案选型为什么选择psutilnetifaces组合经过多个项目的实践验证我最终选择了psutilnetifaces的组合方案。这个选择基于以下对比测试方法跨平台性获取IP类型获取MAC需要权限代码复杂度os.popenifconfig差全是低高(需解析)socket.gethostname中仅IPv4否低低netifaces优全是低中psutil优全否低低组合方案优全是低中单独使用netifaces虽然功能全面但无法直接获取网卡友好名称而psutil可以补足这个缺陷。两者组合后既保持了代码简洁性又获得了最完整的网卡信息。2.2 环境准备与依赖安装推荐使用Python 3.8环境先安装必要依赖pip install psutil netifaces --upgrade如果是内网环境可以使用阿里云镜像加速pip install -i https://mirrors.aliyun.com/pypi/simple/ psutil netifaces3. 完整实现代码解析3.1 获取所有网络接口首先通过psutil获取网卡基础信息import psutil import netifaces def get_adapters(): 获取所有网络接口的适配器信息 adapters [] for name, addrs in psutil.net_if_addrs().items(): adapter { name: name, ipv4: [], ipv6: [], mac: None } # 处理每个地址 for addr in addrs: if addr.family psutil.AF_LINK: adapter[mac] addr.address elif addr.family psutil.AF_INET: adapter[ipv4].append({ address: addr.address, netmask: addr.netmask, broadcast: addr.broadcast }) elif addr.family psutil.AF_INET6: adapter[ipv6].append({ address: addr.address, netmask: addr.netmask }) adapters.append(adapter) return adapters这段代码已经可以获取大部分信息但发现两个问题某些虚拟网卡的MAC地址可能显示为00-00-00-00-00-00Docker创建的虚拟接口会混杂在结果中3.2 增强版实现过滤与补充信息改进后的版本增加了有效性检查和网关信息获取def get_enhanced_adapters(): adapters [] stats psutil.net_if_stats() for name, addrs in psutil.net_if_addrs().items(): # 跳过非活跃接口 if name not in stats or not stats[name].isup: continue adapter { name: name, ipv4: [], ipv6: [], mac: None, gateway: None, isup: stats[name].isup, speed: stats[name].speed } # 处理MAC地址 mac_addrs [addr.address for addr in addrs if addr.family psutil.AF_LINK] if mac_addrs and not mac_addrs[0].startswith(00-00-00): adapter[mac] mac_addrs[0] # 处理IP地址 for addr in addrs: if addr.family psutil.AF_INET: adapter[ipv4].append({ address: addr.address, netmask: addr.netmask, broadcast: addr.broadcast }) elif addr.family psutil.AF_INET6: # 跳过本地IPv6地址 if not addr.address.startswith(fe80): adapter[ipv6].append({ address: addr.address, netmask: addr.netmask }) # 获取网关信息 try: gws netifaces.gateways() adapter[gateway] gws.get(netifaces.AF_INET, [{}])[0].get(gateway) except Exception: pass adapters.append(adapter) return adapters4. 平台差异处理与常见问题4.1 Windows系统特殊处理在Windows平台上需要注意网卡名称可能包含中文和特殊字符虚拟网卡(如VMware)需要特别过滤某些企业环境MAC地址可能被隐藏改进的Windows处理代码if os.name nt: def is_real_adapter(name): exclude (VirtualBox, VMware, Bluetooth, Loopback) return not any(x in name for x in exclude) adapters [a for a in adapters if is_real_adapter(a[name])]4.2 Linux容器环境处理在Docker等容器环境中def is_container_env(): return os.path.exists(/.dockerenv) or os.path.exists(/run/.containerenv) if is_container_env(): # 只获取eth0等主接口 adapters [a for a in adapters if a[name] in (eth0, eth1, ens33)]5. 实用扩展功能5.1 网络连接状态检测结合socket检测网络连通性import socket def check_connection(adapter, timeout2): 检查网络连接状态 if not adapter[ipv4]: return False try: socket.create_connection((8.8.8.8, 53), timeouttimeout) return True except: return False5.2 信息格式化输出生成易读的报告def format_report(adapters): report [] for adapter in adapters: line [ f接口: {adapter[name]}, f状态: {已连接 if adapter[isup] else 断开}, fMAC: {adapter[mac] or 无}, fIPv4: {, .join(ip[address] for ip in adapter[ipv4])}, f网关: {adapter[gateway] or 无} ] report.append(\n.join(line)) return \n\n.join(report)6. 性能优化与生产环境建议缓存机制网卡信息不常变化可以添加缓存from functools import lru_cache lru_cache(maxsize1, ttl60) def get_cached_adapters(): return get_enhanced_adapters()异常处理增强处理权限不足等情况try: adapters get_enhanced_adapters() except PermissionError: print(需要管理员权限获取完整网络信息) adapters get_basic_adapters() # 降级方案日志记录记录网卡变化情况import logging logging.basicConfig(filenamenetwork.log, levellogging.INFO) def log_network_changes(): current {a[name]: a for a in get_enhanced_adapters()} if hasattr(log_network_changes, last_state): for name, adapter in current.items(): if name not in log_network_changes.last_state: logging.info(f新增接口: {name}) elif adapter ! log_network_changes.last_state[name]: logging.info(f接口变更: {name}) log_network_changes.last_state current7. 实际应用案例7.1 服务器健康检查脚本def server_health_check(): adapters get_enhanced_adapters() issues [] for adapter in adapters: if not adapter[isup]: issues.append(f{adapter[name]} 接口未启用) continue if adapter[name].startswith(eth) and not adapter[ipv4]: issues.append(f{adapter[name]} 未配置IPv4地址) if adapter[gateway] and not check_connection(adapter): issues.append(f{adapter[name]} 网关不可达) if issues: send_alert(\n.join(issues)) else: print(所有网络接口正常)7.2 多网卡绑定检测def check_bonding(): adapters get_enhanced_adapters() bond_adapters [a for a in adapters if bond in a[name].lower()] if not bond_adapters: print(未检测到网卡绑定配置) return for bond in bond_adapters: slaves [a for a in adapters if a[mac] bond[mac] and a ! bond] print(f绑定接口 {bond[name]} 包含 {len(slaves)} 个从接口)8. 安全注意事项敏感信息处理MAC地址属于设备唯一标识符在日志或输出中应考虑脱敏def mask_mac(mac): if not mac or mac.count(-) ! 5: return mac parts mac.split(-) return f{parts[0]}-XX-XX-XX-{parts[-1]}权限控制生产环境中应限制脚本执行权限# 设置专用用户和权限 sudo useradd -r netcheck sudo setcap cap_net_raw,cap_net_admineip /usr/bin/python3.8企业环境适配某些企业网络会屏蔽MAC地址采集需要备用方案def get_mac_fallback(interface): try: with open(f/sys/class/net/{interface}/address) as f: return f.read().strip() except: return None我在实际项目中遇到过一个典型问题某台服务器的Docker容器突然无法联网最终发现是主机网卡MAC地址被意外修改导致的。通过这个脚本快速定位了问题比手动检查效率高了十倍不止。现在这个功能已经成为我们运维工具包的标准组件每天自动检查数百台服务器的网络状态。

相关新闻