Python Forum

Full Version: Dictionary using path.
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
I have a dictionary:

{'Q_MGR_NAME': 'BOBBEE2', 'START_DATE': '2024-08-21', 'START_TIME': '05.08.47', 'END_DATE': '2024-08-21', 'END_TIME': '05.09.47', 'COMMAND_LEVEL': 940, 'OBJECT_COUNT': 2, 'Q_STATISTICS_DATA': {'SYSTEM.ADMIN.COMMAND.QUEUE': {'Q_NAME': 'SYSTEM.ADMIN.COMMAND.QUEUE', 'CREATION_DATE': '2023-04-18', 'CREATION_TIME': '12.32.19', 'Q_TYPE': 'LOCAL', 'DEFINITION_TYPE': 'PREDEFINED', 'Q_MIN_DEPTH': 0, 'Q_MAX_DEPTH': 0, 'AVG_Q_TIME': [0, 0], 'PUTS': [17, 0], 'PUTS_FAILED': 0, 'PUT1S': [0, 0], 'PUT1S_FAILED': 0, 'PUT_BYTES': [1512, 0], 'GETS': [17, 0], 'GET_BYTES': [1512, 0], 'GETS_FAILED': 0, 'BROWSES': [0, 0], 'BROWSE_BYTES': [0, 0], 'BROWSES_FAILED': 0, 'MSGS_NOT_QUEUED': 17, 'MSGS_EXPIRED': 0, 'MSGS_PURGED': 0}, 'PYMQI': {'Q_NAME': 'PYMQI', 'CREATION_DATE': '2024-08-14', 'CREATION_TIME': '07.39.31', 'Q_TYPE': 'LOCAL', 'DEFINITION_TYPE': 'PREDEFINED', 'Q_MIN_DEPTH': 40, 'Q_MAX_DEPTH': 60, 'AVG_Q_TIME': [0, 0], 'PUTS': [20, 0], 'PUTS_FAILED': 0, 'PUT1S': [0, 0], 'PUT1S_FAILED': 0, 'PUT_BYTES': [20480, 0], 'GETS': [0, 0], 'GET_BYTES': [0, 0], 'GETS_FAILED': 0, 'BROWSES': [0, 0], 'BROWSE_BYTES': [0, 0], 'BROWSES_FAILED': 0, 'MSGS_NOT_QUEUED': 0, 'MSGS_EXPIRED': 0, 'MSGS_PURGED': 0}}}

I have a routine that gives me the PATH to the two nested dictionaries with Q_NAME elements:

Value SYSTEM.ADMIN.COMMAND.QUEUE found at ['Q_STATISTICS_DATA']['SYSTEM.ADMIN.COMMAND.QUEUE']['Q_NAME']
Value PYMQI found at ['Q_STATISTICS_DATA']['PYMQI']['Q_NAME']

I use this to try to get the list of keys, but get the following error:

print('Keys of = ", new_test_dict.Q_STATISTICS_DATA.SYSTEM.ADMIN.COMMAND.QUEUE.keys())

AttributeError: 'dict' object has no attribute 'Q_STATISTICS_DATA'
(Aug-22-2024, 06:30 PM)Bobbee Wrote: [ -> ]I have a dictionary:

{'Q_MGR_NAME': 'BOBBEE2', 'START_DATE': '2024-08-21', 'START_TIME': '05.08.47', 'END_DATE': '2024-08-21', 'END_TIME': '05.09.47', 'COMMAND_LEVEL': 940, 'OBJECT_COUNT': 2, 'Q_STATISTICS_DATA': {'SYSTEM.ADMIN.COMMAND.QUEUE': {'Q_NAME': 'SYSTEM.ADMIN.COMMAND.QUEUE', 'CREATION_DATE': '2023-04-18', 'CREATION_TIME': '12.32.19', 'Q_TYPE': 'LOCAL', 'DEFINITION_TYPE': 'PREDEFINED', 'Q_MIN_DEPTH': 0, 'Q_MAX_DEPTH': 0, 'AVG_Q_TIME': [0, 0], 'PUTS': [17, 0], 'PUTS_FAILED': 0, 'PUT1S': [0, 0], 'PUT1S_FAILED': 0, 'PUT_BYTES': [1512, 0], 'GETS': [17, 0], 'GET_BYTES': [1512, 0], 'GETS_FAILED': 0, 'BROWSES': [0, 0], 'BROWSE_BYTES': [0, 0], 'BROWSES_FAILED': 0, 'MSGS_NOT_QUEUED': 17, 'MSGS_EXPIRED': 0, 'MSGS_PURGED': 0}, 'PYMQI': {'Q_NAME': 'PYMQI', 'CREATION_DATE': '2024-08-14', 'CREATION_TIME': '07.39.31', 'Q_TYPE': 'LOCAL', 'DEFINITION_TYPE': 'PREDEFINED', 'Q_MIN_DEPTH': 40, 'Q_MAX_DEPTH': 60, 'AVG_Q_TIME': [0, 0], 'PUTS': [20, 0], 'PUTS_FAILED': 0, 'PUT1S': [0, 0], 'PUT1S_FAILED': 0, 'PUT_BYTES': [20480, 0], 'GETS': [0, 0], 'GET_BYTES': [0, 0], 'GETS_FAILED': 0, 'BROWSES': [0, 0], 'BROWSE_BYTES': [0, 0], 'BROWSES_FAILED': 0, 'MSGS_NOT_QUEUED': 0, 'MSGS_EXPIRED': 0, 'MSGS_PURGED': 0}}}

I have a routine that gives me the PATH to the two nested dictionaries with Q_NAME elements:

Value SYSTEM.ADMIN.COMMAND.QUEUE found at ['Q_STATISTICS_DATA']['SYSTEM.ADMIN.COMMAND.QUEUE']['Q_NAME']
Value PYMQI found at ['Q_STATISTICS_DATA']['PYMQI']['Q_NAME']

I use this to try to get the list of keys, but get the following error:

print('Keys of = ", new_test_dict.Q_STATISTICS_DATA.SYSTEM.ADMIN.COMMAND.QUEUE.keys())

AttributeError: 'dict' object has no attribute 'Q_STATISTICS_DATA'
If I print the keys for the entire DICT I get

Keys of patho = dict_keys(['Q_MGR_NAME', 'START_DATE', 'START_TIME', 'END_DATE', 'END_TIME', 'COMMAND_LEVEL', 'OBJECT_COUNT', 'Q_STATISTICS_DATA'])

Q_STATISTICS_DATA is a nested dictionary. I was expecting if I pointed to this I could get the keys of the nested dictionary. NO?
This should help on how to use the nested dictionary.
test_dict = {
    'Q_MGR_NAME': 'BOBBEE2',
    'START_DATE': '2024-08-21',
    'START_TIME': '05.08.47',
    'END_DATE': '2024-08-21',
    'END_TIME': '05.09.47',
    'COMMAND_LEVEL': 940,
    'OBJECT_COUNT': 2,
    'Q_STATISTICS_DATA': {
        'SYSTEM.ADMIN.COMMAND.QUEUE': {
            'Q_NAME': 'SYSTEM.ADMIN.COMMAND.QUEUE',
            'CREATION_DATE': '2023-04-18',
            'CREATION_TIME': '12.32.19',
            'Q_TYPE': 'LOCAL',
            'DEFINITION_TYPE': 'PREDEFINED',
            'Q_MIN_DEPTH': 0,
            'Q_MAX_DEPTH': 0,
            'AVG_Q_TIME': [0, 0],
            'PUTS': [17, 0],
            'PUTS_FAILED': 0,
            'PUT1S': [0, 0],
            'PUT1S_FAILED': 0,
            'PUT_BYTES': [1512, 0],
            'GETS': [17, 0],
            'GET_BYTES': [1512, 0],
            'GETS_FAILED': 0,
            'BROWSES': [0, 0],
            'BROWSE_BYTES': [0, 0],
            'BROWSES_FAILED': 0,
            'MSGS_NOT_QUEUED': 17,
            'MSGS_EXPIRED': 0,
            'MSGS_PURGED': 0
        },
        'PYMQI': {
            'Q_NAME': 'PYMQI',
            'CREATION_DATE': '2024-08-14',
            'CREATION_TIME': '07.39.31',
            'Q_TYPE': 'LOCAL',
            'DEFINITION_TYPE': 'PREDEFINED',
            'Q_MIN_DEPTH': 40,
            'Q_MAX_DEPTH': 60,
            'AVG_Q_TIME': [0, 0],
            'PUTS': [20, 0],
            'PUTS_FAILED': 0,
            'PUT1S': [0, 0],
            'PUT1S_FAILED': 0,
            'PUT_BYTES': [20480, 0],
            'GETS': [0, 0],
            'GET_BYTES': [0, 0],
            'GETS_FAILED': 0,
            'BROWSES': [0, 0],
            'BROWSE_BYTES': [0, 0],
            'BROWSES_FAILED': 0,
            'MSGS_NOT_QUEUED': 0,
            'MSGS_EXPIRED': 0,
            'MSGS_PURGED': 0
        }
    }
}

# Accessing the nested dictionary
q_statistics = test_dict['Q_STATISTICS_DATA'].keys()
print(f"Keys of Q_STATISTICS_DATA = {q_statistics}")

# Accessing PUT_BYTES for SYSTEM.ADMIN.COMMAND.QUEUE
put_bytes = test_dict['Q_STATISTICS_DATA']['SYSTEM.ADMIN.COMMAND.QUEUE']['PUT_BYTES']
print(f"PUT_BYTES for SYSTEM.ADMIN.COMMAND.QUEUE <{put_bytes}>")

# Using nested-lookup at PyPi
# pip install nested-lookup
from nested_lookup import nested_lookup
print(nested_lookup('Q_MAX_DEPTH', test_dict))
Output:
Keys of Q_STATISTICS_DATA = dict_keys(['SYSTEM.ADMIN.COMMAND.QUEUE', 'PYMQI']) PUT_BYTES for SYSTEM.ADMIN.COMMAND.QUEUE <[1512, 0]> [0, 60]
Classes use "." to get an attribute. Dictionaries use [].

Why would you think that new_test_dict.Q_STATISTICS_DATA should give you new_test_dict["Q_STATISTICS_DATA"]? Is new_test_dict a dictionary like you have in your post, or is it some other thing? There is a python package named attrdict that lets you use "." index a dictionary instead of []. A roll your own version.
data = {
    "Q_MGR_NAME": "BOBBEE2",
    "START_DATE": "2024-08-21",
    "START_TIME": "05.08.47",
    "END_DATE": "2024-08-21",
    "END_TIME": "05.09.47",
    "COMMAND_LEVEL": 940,
    "OBJECT_COUNT": 2,
    "Q_STATISTICS_DATA": {
        "SYSTEM.ADMIN.COMMAND.QUEUE": {
            "Q_NAME": "SYSTEM.ADMIN.COMMAND.QUEUE",
            "CREATION_DATE": "2023-04-18",
            "CREATION_TIME": "12.32.19",
            "Q_TYPE": "LOCAL",
            "DEFINITION_TYPE": "PREDEFINED",
            "Q_MIN_DEPTH": 0,
            "Q_MAX_DEPTH": 0,
            "AVG_Q_TIME": [0, 0],
            "PUTS": [17, 0],
            "PUTS_FAILED": 0,
            "PUT1S": [0, 0],
            "PUT1S_FAILED": 0,
            "PUT_BYTES": [1512, 0],
            "GETS": [17, 0],
            "GET_BYTES": [1512, 0],
            "GETS_FAILED": 0,
            "BROWSES": [0, 0],
            "BROWSE_BYTES": [0, 0],
            "BROWSES_FAILED": 0,
            "MSGS_NOT_QUEUED": 17,
            "MSGS_EXPIRED": 0,
            "MSGS_PURGED": 0,
        },
        "PYMQI": {
            "Q_NAME": "PYMQI",
            "CREATION_DATE": "2024-08-14",
            "CREATION_TIME": "07.39.31",
            "Q_TYPE": "LOCAL",
            "DEFINITION_TYPE": "PREDEFINED",
            "Q_MIN_DEPTH": 40,
            "Q_MAX_DEPTH": 60,
            "AVG_Q_TIME": [0, 0],
            "PUTS": [20, 0],
            "PUTS_FAILED": 0,
            "PUT1S": [0, 0],
            "PUT1S_FAILED": 0,
            "PUT_BYTES": [20480, 0],
            "GETS": [0, 0],
            "GET_BYTES": [0, 0],
            "GETS_FAILED": 0,
            "BROWSES": [0, 0],
            "BROWSE_BYTES": [0, 0],
            "BROWSES_FAILED": 0,
            "MSGS_NOT_QUEUED": 0,
            "MSGS_EXPIRED": 0,
            "MSGS_PURGED": 0,
        },
    },
}


class AttributeDictionary:
    def __init__(self, dictionary):
        self.dictionary = dictionary

    def __getattr__(self, attribute):
        part = self.dictionary[attribute]
        if isinstance(part, dict):
            return AttributeDictionary(part)
        return part

    def __str__(self):
        return str(self.dictionary)

    def __repr__(self):
        return repr(self.dictionary)


attr_dict = AttributeDictionary(data)
print(attr_dict.Q_STATISTICS_DATA.PYMQI.PUT_BYTES[0])
print(data["Q_STATISTICS_DATA"]["PYMQI"]["PUT_BYTES"][0])
Or if you just want a dictionary where you can provide a path, that is easier.
data = {
    "Q_MGR_NAME": "BOBBEE2",
    "START_DATE": "2024-08-21",
    "START_TIME": "05.08.47",
    "END_DATE": "2024-08-21",
    "END_TIME": "05.09.47",
    "COMMAND_LEVEL": 940,
    "OBJECT_COUNT": 2,
    "Q_STATISTICS_DATA": {
        "SYSTEM.ADMIN.COMMAND.QUEUE": {
            "Q_NAME": "SYSTEM.ADMIN.COMMAND.QUEUE",
            "CREATION_DATE": "2023-04-18",
            "CREATION_TIME": "12.32.19",
            "Q_TYPE": "LOCAL",
            "DEFINITION_TYPE": "PREDEFINED",
            "Q_MIN_DEPTH": 0,
            "Q_MAX_DEPTH": 0,
            "AVG_Q_TIME": [0, 0],
            "PUTS": [17, 0],
            "PUTS_FAILED": 0,
            "PUT1S": [0, 0],
            "PUT1S_FAILED": 0,
            "PUT_BYTES": [1512, 0],
            "GETS": [17, 0],
            "GET_BYTES": [1512, 0],
            "GETS_FAILED": 0,
            "BROWSES": [0, 0],
            "BROWSE_BYTES": [0, 0],
            "BROWSES_FAILED": 0,
            "MSGS_NOT_QUEUED": 17,
            "MSGS_EXPIRED": 0,
            "MSGS_PURGED": 0,
        },
        "PYMQI": {
            "Q_NAME": "PYMQI",
            "CREATION_DATE": "2024-08-14",
            "CREATION_TIME": "07.39.31",
            "Q_TYPE": "LOCAL",
            "DEFINITION_TYPE": "PREDEFINED",
            "Q_MIN_DEPTH": 40,
            "Q_MAX_DEPTH": 60,
            "AVG_Q_TIME": [0, 0],
            "PUTS": [20, 0],
            "PUTS_FAILED": 0,
            "PUT1S": [0, 0],
            "PUT1S_FAILED": 0,
            "PUT_BYTES": [20480, 0],
            "GETS": [0, 0],
            "GET_BYTES": [0, 0],
            "GETS_FAILED": 0,
            "BROWSES": [0, 0],
            "BROWSE_BYTES": [0, 0],
            "BROWSES_FAILED": 0,
            "MSGS_NOT_QUEUED": 0,
            "MSGS_EXPIRED": 0,
            "MSGS_PURGED": 0,
        },
    },
}


class PathDictionary:
    def __init__(self, dictionary):
        self.dictionary = dictionary

    def __getitem__(self, path):
        value = self.dictionary
        for part in path.split("."):
            value = value[part]
        return value


path_dict = PathDictionary(data)
print(path_dict["Q_STATISTICS_DATA.PYMQI.PUT_BYTES"][0])
print(data["Q_STATISTICS_DATA"]["PYMQI"]["PUT_BYTES"][0])
Thanks, I played with what you presented and it is working. I changed a few things to see if my understanding was correct and that worked. Let me play a little. I eventually want to capture the key/values under each queue and add to them the DEQ and ENQ stats from a Q REST and push them out as CSV to be loaded into an EXCEL sheet whit charts to track. What you gave me helped alot.