2012-02-08 50 views
0
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,然後寫更改回原來的文件後,我找到一個特定的鍵值對錯誤。問題是,即使我做物業的副本列表的字典:「NSCFArray突變而被枚舉」枚舉副本

copy = NSDictionary.dictionaryWithDictionary_(pl) 

這是給我的標準「的突變,同時列舉了」錯誤,當我編輯原始的,只是循環鍵作爲獨立插件(注意缺乏引號)。

del pl['Sets'][Set]['Network']['Interface'][enX][key]['PreferredNetworks'][index] 

是我的語法在某種程度上導致它嘗試和編輯pl的字典那麼copy?下面是輸出:

... Processing Set: D5C0A0F4-613A-4121-B6AE-4CBA6E2635FF Processing enX: en1 Processing key: AirPort Traceback (most recent call last): File "/Users/tester/Desktop/wifiutil", line 1164, in sys.exit(main()) File "/Users/tester/Desktop/wifiutil", line 1135, in main removeWireless(osVersion,network) File "/Users/tester/Desktop/wifiutil", line 1051, in removeWireless leopardRemoveWireless(network)
File "/Users/tester/Desktop/wifiutil", line 528, in leopardRemoveWireless for PreferredNetwork in copy['Sets'][Set]['Network']['Interface'][enX][key]['PreferredNetworks']: File "/System/Library/Frameworks/Python.framework/Versions/2.5/Extras/lib/python/PyObjC/objc/_convenience.py", line 431, in enumeratorGenerator yield container_unwrap(anEnumerator.nextObject(), StopIteration) objc.error: NSGenericException - * Collection was mutated while being enumerated.

回答

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()來測試。

你必須要麼是原始字典的全深拷貝,或(可能更好),你列舉的前幾天最後一級的副本。

+0

我嘗試切換它來複制= NSMutableDictionary.alloc()。initWithDictionary_copyItems_(PL,真) 但仍然有同樣的錯誤。也許我應該製作NSArray的副本? – acidprime 2012-02-08 19:29:38

+0

是的,這仍然不會做一個完整的副本 - 如果你看[文檔](https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSDictionary_Class /Reference/Reference.html#//apple_ref/doc/uid/20000140-BABECHBH)你會看到它只複製第一層;這是你必須自己編碼的東西。幸運的是,在Python中這比ObjC容易得多,但我仍然認爲最好的方法是在枚舉它之前複製最後一個元素。 – 2012-02-08 19:37:17

+0

copy = NSMutableDictionary.dictionaryWithContentsOfFile_(plistPath)雖然對內存管理來說不是最好的。 – acidprime 2012-02-08 19:58:06