基于Pyobjc与CoreWLAN实现macOS废弃airport工具的格式兼容替代
替代macOS Sonoma 14.4+废弃的airport工具
原airport工具说明
Apple曾提供/System/Library/PrivateFrameworks/Apple80211.framework/Versions/A/Resources/airport二进制工具,可扫描Wi-Fi并生成如下格式的输出:
SSID BSSID RSSI CHANNEL HT CC SECURITY (auth/unicast/group) vodafone20645C -89 6 Y -- RSN(PSK/AES/AES) vodafone20645C -89 60 Y -- RSN(PSK/AES/AES) ALCL-HGU -88 1 Y -- RSN(PSK/AES/AES) SKY69QVQ -84 11 Y -- RSN(PSK/AES/AES)
但自macOS Sonoma 14.4起,该工具被废弃,执行时会报错:
WARNING: The airport command line tool is deprecated and will be removed in a future release. For diagnosing Wi-Fi related issues, use the Wireless Diagnostics app or wdutil command line tool.
且官方推荐的替代工具无法满足原有格式需求。
现有代码问题
基于CoreWLAN的pyobjc封装,已实现基础扫描,但输出格式与原工具不符:缺少安全字段、未做列对齐、数据结构不符合原工具的文本格式。现有代码片段:
for i in networks: if i.ssid() is None: continue print({'SSID_STR': i.ssid(), 'BSSID': i.bssid(), 'RSSI': i.rssiValue(), 'CHANNEL': i.channel()})
当前输出:
{'SSID_STR': 'vodafone20645C', 'BSSID': None, 'RSSI': -89, 'CHANNEL': 6} {'SSID_STR': 'vodafone20645C', 'BSSID': None, 'RSSI': -89, 'CHANNEL': 60} {'SSID_STR': 'ALCL-HGU', 'BSSID': None, 'RSSI': -88, 'CHANNEL': 1} {'SSID_STR': 'SKY69QVQ', 'BSSID': None, 'RSSI': -84, 'CHANNEL': 11}
复刻原格式的Python实现
以下代码完全匹配原airport工具的输出格式,包括SSID右对齐、补全所有缺失字段、格式对齐:
import objc from CoreWLAN import CWInterface, CWNetwork # 获取默认Wi-Fi接口 interface = CWInterface.interface() # 执行网络扫描 networks, error = interface.scanForNetworksWithName_error_(None, None) # 定义列宽,严格匹配原airport工具的排版 COL_WIDTHS = { 'SSID': 28, 'BSSID': 18, 'RSSI': 4, 'CHANNEL': 7, 'HT': 2, 'CC': 3, 'SECURITY': 25 } # 打印表头 header = f"{'SSID':>{COL_WIDTHS['SSID']}} {'BSSID':>{COL_WIDTHS['BSSID']}} {'RSSI':>{COL_WIDTHS['RSSI']}} {'CHANNEL':>{COL_WIDTHS['CHANNEL']}} {'HT':>{COL_WIDTHS['HT']}} {'CC':>{COL_WIDTHS['CC']}} {'SECURITY (auth/unicast/group)'}" print(header) for network in networks: ssid = network.ssid() or "" if not ssid: continue # 提取各字段数据 bssid = network.bssid() or "" rssi = str(network.rssiValue()) channel = str(network.channel()) ht = "Y" if network.supportsHT() else "N" cc = network.countryCode() or "--" # 解析安全类型,匹配原工具的输出格式 security_type = network.securityType() sec_str = "NONE" if security_type == CWNetwork.SecurityTypeWEP: sec_str = "WEP" elif security_type == CWNetwork.SecurityTypeWPA: sec_str = "WPA(PSK/TKIP/TKIP)" elif security_type == CWNetwork.SecurityTypeWPA2: sec_str = "RSN(PSK/AES/AES)" if not network.supportsWPA2Enterprise() else "RSN(802.1X/AES/AES)" elif security_type == CWNetwork.SecurityTypeWPA3: sec_str = "SAE(PSK/AES/AES)" # 按列宽格式化输出,复刻原工具的右对齐排版 output_line = ( f"{ssid:>{COL_WIDTHS['SSID']}} " f"{bssid:>{COL_WIDTHS['BSSID']}} " f"{rssi:>{COL_WIDTHS['RSSI']}} " f"{channel:>{COL_WIDTHS['CHANNEL']}} " f"{ht:>{COL_WIDTHS['HT']}} " f"{cc:>{COL_WIDTHS['CC']}} " f"{sec_str}" ) print(output_line)
前置要求
- 安装依赖包:
pip install pyobjc-core pyobjc-framework-CoreWLAN - 首次运行需授予位置服务权限(CoreWLAN获取BSSID需此授权)
内容的提问来源于stack exchange,提问作者John Lockwood
相关产品推荐
相关产品推荐

