def leopardRemoveWireless(networkName):
plistPath = '/Library/Preferences/SystemConfiguration/preferences.plist'
# Sanity checks for the plist
if os.path.exists(plistPath):
try:
pl = NSMutableDictionary.dictionaryWithContentsOfFile_(plistPath)
except:
print 'Unable to parse file at path: %s' % plistPath
sys.exit(1)
else:
print 'File does not exist at path: %s' % plistPath
sys.exit(1)
# Create a copy of the dictionary due to emuration
copy = NSDictionary.dictionaryWithDictionary_(pl)
# Iterate through network sets
for Set in copy['Sets']:
UserDefinedName = copy['Sets'][Set]['UserDefinedName']
print 'Processing location: %s' % UserDefinedName
for enX in copy['Sets'][Set]['Network']['Interface']:
print 'Processing interface: %s' % enX
# I think this will always be a single key but this works either way
for key in copy['Sets'][Set]['Network']['Interface'][enX]:
print 'Processing Service: %s' % key
# Try to grab the PreferredNetworks key if any
try:
# Iterate through preferred network sets
index = 0
for PreferredNetwork in copy['Sets'][Set]['Network']['Interface'][enX][key]['PreferredNetworks']:
SSID_STR = PreferredNetwork['SSID_STR']
print 'Processing SSID: %s' % SSID_STR
# If the preferred network matches our removal SSID
if SSID_STR == networkName:
print 'Found SSID %s to remove' % SSID_STR
# Delete our in ram copy
print 'Processing Set: %s' % Set
print 'Processing enX: %s' % enX
print 'Processing key: %s' % key
del pl['Sets'][Set]['Network']['Interface'][enX][key]['PreferredNetworks'][index]
index += 1
except KeyError:
print 'Skipping interface without PreferredNetworks'
我正在编辑一个相当复杂的(字典)plist,然后在找到特定的键值对后将更改写回文件。问题是,即使我正在制作属性列表字典的副本:
copy = NSDictionary.dictionaryWithDictionary_(pl)
当我编辑原始文件时,它给了我标准的“枚举时突变”错误,只是将循环键作为标记(注意缺少引号)。
del pl['Sets'][Set]['Network']['Interface'][enX][key]['PreferredNetworks'][index]
我的语法是否以某种方式导致它尝试编辑pl
词典而不是copy
?这是输出:
... 处理组:D5C0A0F4-613A-4121-B6AE-4CBA6E2635FF 处理enX:en1 处理密钥:AirPort Traceback(最近一次调用最后一次): 文件“/ Users / tester / Desktop / wifiutil”,第1164行,in sys.exit(主()) 文件“/ Users / tester / Desktop / wifiutil”,第1135行,主要 removeWireless(OSVERSION,网络) 文件“/ Users / tester / Desktop / wifiutil”,第1051行,在removeWireless中 leopardRemoveWireless(网络)
在leopardRemoveWireless中输入文件“/ Users / tester / Desktop / wifiutil”,第528行 for CopyNetwork in copy ['Sets'] [Set] ['Network'] ['Interface'] [enX] [key] ['PreferredNetworks']: 在enumeratorGenerator中输入文件“/System/Library/Frameworks/Python.framework/Versions/2.5/Extras/lib/python/PyObjC/objc/_convenience.py”,第431行 yield container_unwrap(anEnumerator.nextObject(),StopIteration) objc.error:NSGenericException - * 集合在枚举时发生了变异。
答案 0 :(得分:1)
我认为问题是字典的嵌套性质。 dictionaryWithDictionary_()
没有做类似深层复制的任何事情;它只是创建一个新的NSDictionary
并复制值的指针(它确实复制了键本身,因为这是NSDictionary
的性质。)
这意味着,虽然您有一个可用于枚举的新顶级,但内部字典和数组与原始字体完全相同。
你的最后一个循环:
for PreferredNetwork in copy['Sets'][Set]['Network']['Interface'][enX][key]['PreferredNetworks']:
枚举其中一个内部数组,然后尝试使用del
语句进行变异:
del pl['Sets'][Set]['Network']['Interface'][enX][key]['PreferredNetworks'][index]
没有复制;它与您在for
中使用的数组对象相同,这会导致异常。您可以通过将两个表达式传递给id()
来测试它。
您必须要么对原始字典进行全面深度复制,要么(可能更好)在枚举之前获取最后一个级别的副本。