Python Forum
Accessing nested dictionary values. Plistlib, Python 2.7
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Accessing nested dictionary values. Plistlib, Python 2.7
#11
I am on python 2.7. I hope to use other modules alongside it such as 'pyautogui' and 'pyperclip'. I know that they work on my macOS 10.12 machine.

I'll have to come back tomorrow with an SPX file. I am a but unsure of posting my own here (right now) as it would contain potentially personal info such as which VPNs and wifi networks I've connected to, as well as serials and UUIDs etc.

I am still very enthused by the help I've received on this forum.

William
Reply
#12
for y in candidates2:
    for item in y['_items']:
        for item2 in item['_items']:
                for volume in item2['volumes']:
                    print volume['size']
Output:
209.7 MB 499.42 GB 650 MB
Reply
#13
Wow! That has worked.

I am in debt in your debt.

Thanks again.

Wow! That has worked.

I am in your debt!

Thanks again.
Reply
#14
just to make sure you understand:
1.y is a dict
2. y['_items'] is a list of dicts, so I don't know how many elements it has, so we must iterate. of course you can access elements by index like you did y['_items'][0] but you don't know if there are more elements...
3. each of the dicts (item) that we iterate over in step 2 has again an element with key '_items' which is again list of dicts.
4. we iterate over these (item2)
5. each item2 is a dict that has element with key 'volumes' which is a list of dicts
6. we iterate over these lists (volume) and extract element with key 'size'
Reply
#15
Cool. That has made things very clear.

I can now adapt the code you've given me to gather data from other nested hardware attributes in the .spx file.
Reply
#16
Hi again guys.

I've been getting my hands a bit more dirty with 'for loops' and dictionaries, especially those that are nested.

I've adapted the code buran gave me so that it give me back the physical size of the hard drive in a given machine instead of the size of each of the individual volumes or partitions.

I've also added some formatting checks to get the size of the hard drives correct i.e no messy numbers such as 500.11 GB and also that SSD drives return a pretty binary value such as 128 GB etc.

for y in candidates2:
    for item in y['_items']:
        for item2 in item['_items']:
            HDsize = item2['size']
            typeofHD = item2['spsata_medium_type']
            if len(HDsize) >= 5 and typeofHD == "Rotational":
                HDsize = HDsize[0:3]
                HDsize = HDsize + "GB"
            elif len(HDsize) >= 5 and typeofHD == "Solid State":
                HDsize = HDsize[0:3]
                HDsize = HDsize + "GB-SSD"
                if HDsize == "121GB-SSD":
                    HDsize = "128GB-SSD"
                elif HDsize == "251GB-SSD":
                    HDsize = "256GB-SSD"
                elif HDsize == "500GB-SSD":
                    HDsize = "512GB-SSD"
            elif HDsize == "1 TB":
                HDsize = "1TB"
One little snag that remains is that when the script is executed on .spx saved from a machine with a internal hard drive AND a Superdrive (for reading CDs/DVDs) the script crashed. I get a KeyError: 'size' message. This is most likely due to two different devices being attached to the SATA bus and each having its own dictionary. The script does not know which one to read to get at HD size info etc.

I've run this to help isolate things down a bit...

for y in candidates2:
    for item in y['_items']:
        for item2 in item['_items']:
            print item2
            print ""
The output is two distinct dictionaries. The data I want to get at is always on the first.
Macs with just one internal drive always return one dictionary when I run the exact same 'for' loop.

{'spsata_portspeed': '3 Gigabit', 'spsata_negotiatedlinkspeed': '3 Gigabit', '_name': 'NVidia MCP79 AHCI', 'spsata_product': 'MCP79 AHCI', 'spsata_physical_interconnect': 'SATA', 'spsata_vendor': 'NVidia', 'spsata_portdescription': 'AHCI Version 1.20 Supported', '_items': [{'smart_status': 'Failing', 'detachable_drive': 'no', 'spsata_rotational_rate': 7200, 'spsata_ncq_depth': '32', 'device_model': 'ST3500418ASQ                            ', 'size_in_bytes': 500107862016, '_name': 'ST3500418ASQ', 'spsata_ncq': 'Yes', 'bsd_name': 'disk0', 'device_revision': 'AP24    ', 'volumes': [{'size': '209,7 MB', 'iocontent': 'EFI', 'bsd_name': 'disk0s1', 'size_in_bytes': 209715200, '_name': 'EFI'}, {'mount_point': u'/Volumes/*A\u0308U\u0308P\xdfO\u0308-IK9,JMU8HNZ7BGT6FRV54SWX3AQY2', 'size_in_bytes': 499248103424, 'iocontent': 'Apple_HFS', 'free_space': '498,8 GB', 'writable': 'yes', 'bsd_name': 'disk0s2', 'volume_uuid': '7E8EFE9A-C246-3382-AEF1-EAF6F4EFFFE8', '_name': u'*A\u0308U\u0308P\xdfO\u0308-IK9,JMU8HNZ7BGT6FRV54SWX3AQY2', 'free_space_in_bytes': 498799886336, 'file_system': 'Journaled HFS+', 'size': '499,25 GB'}, {'iocontent': 'Apple_Boot', '_name': 'Recovery HD', 'bsd_name': 'disk0s3', 'volume_uuid': '82E27D91-EFB0-381D-9DC8-8A1A25FEA879', 'size_in_bytes': 650002432, 'size': '650 MB'}], 'spsata_medium_type': 'Rotational', 'device_serial': '            5VMASEQK', 'removable_media': 'no', 'partition_map_type': 'guid_partition_map_type', 'size': '500,11 GB'}]}
 
{'spsata_portspeed': '3 Gigabit', 'spsata_negotiatedlinkspeed': '1.5 Gigabit', '_name': 'NVidia MCP79 AHCI', 'spsata_product': 'MCP79 AHCI', 'spsata_physical_interconnect': 'SATA', 'spsata_vendor': 'NVidia', 'spsata_portdescription': 'AHCI Version 1.20 Supported', '_items': [{'detachable_drive': 'no', 'device_model': 'HL-DT-ST DVDRW  GA11N                   ', 'spsata_power_off': 'No', '_name': 'HL-DT-ST DVDRW  GA11N', 'spsata_ncq': 'No', 'spsata_async_notify': 'Yes', 'device_revision': 'JA18    ', 'device_serial': 'KZKA2AD2212         '}]}
 
I've done some research online but I tend to find the advice offered a bit to technical to digest.

The python code I've attached to the post. A sample SPX file (which crashes the script) is on my dropbox.com

Thanks again,

Will

Attached Files

.py   extractHWinfo.py (Size: 2.51 KB / Downloads: 255)
Reply
#17
(Sep-28-2017, 07:02 PM)williamlombard Wrote:
for item2 in item['_items']:
    HDsize = item2['size']

Sounds like things that aren't hard drives, don't have a size.  So, check if size exists before getting it:
for item2 in item["_items"]:
    if "size" in item2:
        HDsize = item2["size"]
        # etc
Reply
#18
HDsize = item2.get("size", None) # you can change the default value from None to empty string 0 or what ever you want
Reply
#19
@nilamo

I tried out
for y in candidates2:
    for item2 in y["_items"]:
        if "size" in item2:
            HDsize = item2['size']



print HDsize
but got back NameError: name 'HDsize' is not defined

Thanks for your help
Reply
#20
That's simple: don't reference things outside of the scope they're defined in.
ie: fix your indentation.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
Question Using Lists as Dictionary Values bfallert 8 312 Apr-21-2024, 06:55 AM
Last Post: Pedroski55
  need to compare 2 values in a nested dictionary jss 2 867 Nov-30-2023, 03:17 PM
Last Post: Pedroski55
  Printing specific values out from a dictionary mcoliver88 6 1,415 Apr-12-2023, 08:10 PM
Last Post: deanhystad
  Accessing same python script from multiple computers bigrockcrasher 1 1,709 May-25-2022, 08:35 PM
Last Post: Gribouillis
  Python modules for accessing the configuration of relevant paths Imago 1 1,383 May-07-2022, 07:28 PM
Last Post: Larz60+
Question How to print each possible permutation in a dictionary that has arrays as values? noahverner1995 2 1,749 Dec-27-2021, 03:43 AM
Last Post: noahverner1995
  plistlib / xml file / get value except key Tecuma 6 3,253 May-26-2021, 03:51 PM
Last Post: Tecuma
  Nested dictionary acting strange Pedroski55 2 2,107 May-13-2021, 10:37 PM
Last Post: Pedroski55
  format the output from a nested dictionary. nostradamus64 9 4,592 May-03-2021, 04:45 PM
Last Post: nostradamus64
Lightbulb Python Nested Dictionary michaelserra 2 2,618 Apr-18-2021, 07:54 AM
Last Post: michaelserra

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020