用plistlib解析system_profiler生成plist取serial_number报'int'不可下标
报错根源定位
报错'int' object is not subscriptable和你推测的“取值层级逻辑错误”无关,问题出在生成plist文件的步骤逻辑完全错位:
- 执行
subprocess.check_output(cmd)拿到的plist变量,是system_profiler直接输出的、已经是合法plist格式的二进制字节流,不是Python内存中的结构化对象 - 你错误地把这堆原始字节流,当成普通Python对象传给
plistlib.dump(plist, fp)写入文件——plistlib.dump的作用是把内存里的Python字典/数组序列化成plist格式,不是帮你存储已经是plist格式的原始字节 - 这步操作写出来的
hardware.plist是完全损坏的非标准文件,后续用plistlib.load读取时解析出来的结构完全偏离预期,走到索引取值的步骤碰到int类型的值,才会触发“int对象不能用下标访问”的报错。
修正方案
逻辑校准要点
- 系统输出的原始plist字节流,如果要落盘,直接按二进制写入即可,不需要走
plistlib.dump的序列化流程 - 解析plist时不需要绕路读损坏的文件,直接把原始字节流传给
plistlib.loads在内存中解析即可,减少不必要的IO开销 - 你原本写的取值路径
pl[0]['_items'][0]['serial_number']是完全符合给出的合法plist结构的,不需要修改取值逻辑。
修正后可运行的代码
import subprocess import plistlib def get_serial_number(): cmd = ['system_profiler', 'SPHardwareDataType', '-xml'] # 获取system_profiler输出的原生plist二进制内容 raw_plist = subprocess.check_output(cmd) # 需要落盘存文件的话,直接写原始字节即可 with open('hardware.plist', 'wb') as fp: fp.write(raw_plist) # 直接内存解析plist内容,不需要读本地文件 parsed_data = plistlib.loads(raw_plist) # 原取值路径逻辑正确,直接用即可 serial = parsed_data[0]['_items'][0]['serial_number'] return serial
额外提示:之前生成的损坏plist文件可以先删掉再跑修正后的代码,避免旧文件残留导致误判。
内容的提问来源于stack exchange,提问作者rynoknows
相关产品推荐
相关产品推荐

