Skylark
Skylark

Reputation: 3

Python selecting variables based inside function

I'm trying to create function that can pull information from an API library and I am having a hard time figuring out how to pass a variable selection into the function without being read as a value.

code example:

def get_list(api, val = None):
    response =[]
    list = api
    for i in list:
        response.append(f'i.{val}')
    return (response)


devices = get_list(api.devices.all(), 'name')

print(devices )

Give me a long list of "i.name"

I need to resolve i.name as a variable selection and not as an actual value

I have tired:

response.append(vars()[f'i.{val}']) # locals(), globals()

But I I get the error: "KeyError: 'i.name'"

I think the problem is the 'i.name' doesn't really exist as a variable within the function.

Upvotes: 0

Views: 109

Answers (4)

PanTrakX
PanTrakX

Reputation: 71

From what I understand is that you want to write a function so you will not have to repeat the for

ip_list = []
for device in lnms.devices.all():
    ip_list.append(device.ip)

name_list = []
for device in lnms.devices.all():
    ip_list.append(device.sysName)

First of all on your code, you are using list as a variable which you should not cause list is a built-in keyword.

This comment explains why your code doesn't work

This is how it would work

def get_data(devices, attr):
    response = []
    for device in devices:
        response.append(getattr(device, attr))
    return response

Or even shorter using list comprehension

def get_data(devices, attr):
    return [getattr(device, attr) for device in devices]

and then you can do

ip_list = []
ip_list = get_data(lnms.devices.all(), 'ip')

name_list = []
name_list = get_data(lnms.devices.all(), 'sysName')

And if you don want to repeat lnms.devices.all() You can write the functions like

def get_data_from_devices(attr):
    response = []
    for device in lnms.devices.all():
        response.append(getattr(device, attr))
    return response

Or with list comprehension

def get_data_from_devices(attr):
    return [getattr(device, attr) for device in lnms.devices.all()]

And then you would call them as

ip_list = []
ip_list = get_data_from_devices('ip')

name_list = []
name_list = get_data_from_devices('sysName')

PS: Needs better names for functions

Upvotes: 0

Skylark
Skylark

Reputation: 3

I am pretty new at Python and I can see from the text above I have not explained myself very well, so here is my attempt to make things clearer.

command "lnms_device_names = get_data(lnms.devices.all(), 'sysName')"

Original attempts:



def get_data(devices, key):
    response = []
    for device in devices:
        response.append(device.key)
    return response

# => Endpoint devices/29/key does not exists

def get_data(devices, key):
    response = []
    for device in devices:
        response.append(f'device.{key}')
    return response

# => ['device.sysName', 'device.sysName', 'device.sysName', 'device.sysName']

Failed attempts using advice in this thread:

def get_data(devices, key):
    return [device[key] for device in devices]

# => TypeError: 'LibreNMSEndpoint' object is not subscriptable

def get_data(devices, key):
    response = []
    for device in devices:
        response.append(device[key])
    return response

# => TypeError: 'LibreNMSEndpoint' object is not subscriptable

def get_data(devices, key):
    response = []
    for device in devices:
        response.append(f'{device}.{key}') # same result with f'{str(device)}.{key}'
    return response

# => full data dump no filtering by key

how it looks when no function is used

#WORKS:
lnms_device_names = []
for device in lnms.devices.all():
    lnms_device_names.append(device.sysName)

# => ['dc2-h1-ipn03', 'dc2-h1-spine1', 'dc2-h1-spine2', 'dc2-h1-leaf1']

Data structure:

{
            "device_id": 1,
            "inserted": "2022-08-15 15:50:33",
            "hostname": "172.21.142.10",
            "sysName": "dc2-h1-ipn03",
            "display": null,
            "ip": "",
            "overwrite_ip": null,
            "community": "xxxxxxx",
            "authlevel": null,
            "authname": null,
            "authpass": null,
            "authalgo": null,
            "cryptopass": null,
            "cryptoalgo": null,
            "snmpver": "v2c",
            "port": 161,
            "transport": "udp",
            "timeout": null,
            "retries": null,
            "snmp_disable": 0,
            "bgpLocalAs": 1,
            "sysObjectID": ".1.3.6.1.4.1.9.12.3.1.3.1812",
            "sysDescr": "Cisco NX-OS(tm) nxos.7.0.3.I7.9.bin, Software (nxos), Version 7.0(3)I7(9), RELEASE SOFTWARE Copyright (c) 2002-2020 by Cisco Systems, Inc. Compiled 8/27/2020 4:00:00",
            "sysContact": null,
            "version": "7.0(3)I7(9)",
            "hardware": "N9K-C93180YC-EX",
            "features": null,
            "location_id": 1,
            "os": "nxos",
            "status": 1,
            "status_reason": "",
            "ignore": 0,
            "disabled": 0,
            "uptime": 47671869,
            "agent_uptime": 0,
            "last_polled": "2022-11-02 15:28:35",
            "last_poll_attempted": null,
            "last_polled_timetaken": 8.46,
            "last_discovered_timetaken": 293.18,
            "last_discovered": "2022-11-02 12:05:18",
            "last_ping": "2022-11-02 15:31:02",
            "last_ping_timetaken": 1.83,
            "purpose": null,
            "type": "network",
            "serial": "xxxxxx",
            "icon": "cisco.svg",
            "poller_group": 0,
            "override_sysLocation": 0,
            "notes": null,
            "port_association_mode": 1,
            "max_depth": 0,
            "disable_notify": 0,
            "dependency_parent_id": null,
            "dependency_parent_hostname": null,
            "location": "xxxxx",
            "lat": 64.132453,
            "lng": -21.877419
        },
        {
            "device_id": 2,
            ....
            ....

Upvotes: 0

Skylark
Skylark

Reputation: 3

I'm using a LibrenmsAPI library to read data from LibreNMS

regular GET request would look like:

ip_list []
for device in lnms.devices.all():
    ip_list.append(device.ip)

name_list []
for device in lnms.devices.all():
    ip_list.append(device.sysName)

So in order not have to make every variation of an api request I need, the idea would be to have a "list" function.

Upvotes: 0

Rihhard
Rihhard

Reputation: 66

When you call this function with devices, you are passing the argument 'name' as your "val" which you then loop over and append to results.

It would be helpful if you could also include what your desired result here would be since that is not clear at the moment.

Upvotes: 1

Related Questions