Seite 1 von 2
Mehrdimensionales Array abfragen
Verfasst: Freitag 4. September 2015, 08:21
von trumm
Hallo zusammen,
ich beschäftige mich gerade ganz frisch mit Python, aber ich komme an einer stelle gerade nicht weiter.
Ich habe eine Array und möchte wissen ob ein bestimmter Wert in dem zweiten Tail de Liste vorkommt.
Die Liste sieht wie folgt aus.
Code: Alles auswählen
[[['1', 'GigabitEthernet1', '6'],
['2', 'GigabitEthernet2', '6'],
['3', 'GigabitEthernet3', '6'],
['4', 'Null0', '1'],
['5', 'Loopback10', '24'],
['6', 'Tunnel25', '131'],
['7', 'Tunnel5025', '131']],
[['3'], ['7']]]
Ziel ist es erst auf die 131 zu filtern. In diesem Fall soll nur Index 6 und 7 überbleiben.
Anschliessen soll in der zweiten Liste, ich hoffe überhaupt das es eine ist, gepüft werden ob 6 oder 7 darin vorkommt.
Den ersten Teil habe ich wie folgt gelöst :
Code: Alles auswählen
for line in info:
interface = line[1]
type = line[2]
if type == "131":
Ich bin mir nicht sicher ob das alles so klappt und hoffe Ihr könnt mir helfen.
Danke & Gruß
Sascha
Re: Mehrdimensionales Array abfragen
Verfasst: Freitag 4. September 2015, 08:25
von snafu
Ja, das dürfte so funktionieren, wie du es beschrieben hast. Warum probierst du es nicht einfach selbst aus? Gibt es ein Problem bei der konkreten Umsetzung?
Re: Mehrdimensionales Array abfragen
Verfasst: Freitag 4. September 2015, 09:06
von /me
Du möchtest Daten anhand eines bestimmten Kriteriums herausfiltern, so dass nur die übrigbleiben die die Bedingung erfüllen.
Nehmen wir mal an du hast folgende Definition.
Code: Alles auswählen
data = [[['1', 'GigabitEthernet1', '6'],
['2', 'GigabitEthernet2', '6'],
['3', 'GigabitEthernet3', '6'],
['4', 'Null0', '1'],
['5', 'Loopback10', '24'],
['6', 'Tunnel25', '131'],
['7', 'Tunnel5025', '131']],
[['3'], ['7']]]
info = data[0]
Dann kannst du eine neue leere Liste definieren und alle Elemente dort anfügen die die Bedingung erfüllen. Das ist platt runtergeschrieben und funktioniert.
Code: Alles auswählen
filtered_info = []
for element in data[0]:
if element[2] == '131':
filtered_info.append(element)
print(filtered_info)
Du kannst aber natürlich auch die
filter Funktion einsetzen. Diese erwartet als ersten Parameter eine Funktion die ein Element übergeben bekommt und als zweites ein Iterable (wie z.B. eine Liste) auf das der Filter angewendet wird. Das Iterable haben wir, das sind deine Ausgangsdaten.
Die Filterfunktion würde dann wie folgt aussehen.
Code: Alles auswählen
# Filterfunktion
def is_correct_type(element):
if element[2] == '131':
return True
else:
return False
# alternative Filterfunktion (sinnvoll gekürzt)
def is_correct_type(element):
return element[2] == '131'
Der Aufruf ist jetzt einfach.
Mit einem lambda-Ausdruck kannst du das sogar in einer Zeile unterbringen.
Code: Alles auswählen
filtered_info = list(filter(lambda element: element[2] == '131', info))
Re: Mehrdimensionales Array abfragen
Verfasst: Freitag 4. September 2015, 09:32
von garreth
Ich wollte nur noch kurz einwerfen, dass "type" ein schlechter Bezeichner ist. Man überschreibt so die eingebaute Funktion "type()".
Re: Mehrdimensionales Array abfragen
Verfasst: Freitag 4. September 2015, 09:40
von Kebap
Hey Sascha, willkommen bei Python und hier im Forum!
Ich bin mir nicht sicher ob das alles so klappt und hoffe Ihr könnt mir helfen.
Da empfiehlt sich die interaktive Python Konsole. Du kannst dort einfach paar Befehle eingeben, und sie werden direkt ausgeführt. So kannst du etwas herumprobieren, ob die Logik wohl funktioniert, die du dir gerade ausdenkst. Wenn ja, kannst du sie in deinen Programmcode aufnehmen und dich dem nächsten Teilproblem zuwenden.

Re: Mehrdimensionales Array abfragen
Verfasst: Freitag 4. September 2015, 10:09
von trumm
Herzlichen Dank euch allen.
Erstmal, ich werde den Einwand für Type beherzigen und den Ausdruck ändern.
Mit der interaktiven Shell das hab ich verstenden nur auf die schnelle keine gefunden. Ich hab mir jetzt so eine Python für Windows installiert, aber damit komme ich gerade nicht so zurecht, der will nicht mal ein print ausführen. Egal.
Meinen besonderen Dank gilt /me

Dieses ausführliche Anleitung ist ganz toll, aber ich verstehe es leider noch nicht.
Ich hab verstanden, dass ich eine neue Liste generiere.
Aber das ausfiltern will nicht in meinen Kopf.
Ich brauche erstmal die Interfaces vom Type 131 und deren Index ['6', 'Tunnel25', '131'],
['7', 'Tunnel5025', '131'] , aber eben auch den zweiten Teil der Liste in diesem Fall hinten die [3, 7].
Dann muss ich vergleichen ob 6 und 7 in Liste zwei [3, 7] vorkommt. Wenn dieser fehlt dann Error.
Wie kann ich Liste eins durchlaufen und prüfen ob in zwei der Wert auch vorhanden ist.
Gruß
Sascha
Re: Mehrdimensionales Array abfragen
Verfasst: Freitag 4. September 2015, 10:37
von Hyperion
Vielleicht solltest Du das dann in eine sinnvollere Datenstruktur überführen! Woher kommt denn die initiale Liste?
Für den "zweiten Teil" böte sich ein ``set`` an; damit kann man einfach auf das Vorhandensein eines Elements prüfen.
Für den ersten ggf. eine Liste oder gar ein Dictionary, wenn die Ids zu Beginn nicht fortlaufend sind.
Allerdings hast Du keine "zweite" Liste, denn Du hast darin lauter *einelementige* Listen. Ist das so gewollt?
Re: Mehrdimensionales Array abfragen
Verfasst: Freitag 4. September 2015, 10:45
von trumm
Die Liste kommt aus einer snmp Abfrage eines Cisco Switches.
Um die Infos zusammen zu bekommen, muss ich unterschiedliche OIDs abfragen. Darauf ergibt sich das Konstrukt, auch wenn ich jetzt noch nicht weiß wie die richtigen Fachbegriffe dafür sind. An dem Output kann ich wenig ändern, bzw fehlt mir bsiher das know how, ich bin schon froh, dass ich das überhaupt habe
Mein Abfrage auf True / False klingt ungefähr so:
Suche per SNMP alle Interfaces raus. Da kommt der erste Teil her [ Interface_Index, Interface_Name, Type ]
Dann sage ich, mich Interessieren nur die mit dem Typ 131 und dann davon der Interface_Index und Interface_Name.
Als zweites muss ich wissen on der Interface_Index in dem zweiten Teil vorhanden ist. wenn Nein dann False
Ich hab da noch nen Knoten im Kopf
Aktuell sieht es so aus, das ich eine weitere Liste aufgemacht habe. Die Idee hab ich aus dem Post von /me
Code: Alles auswählen
info = [[['1', 'GigabitEthernet1', '6'],
['2', 'GigabitEthernet2', '6'],
['3', 'GigabitEthernet3', '6'],
['4', 'Null0', '1'],
['5', 'Loopback10', '24'],
['6', 'Tunnel25', '131'],
['7', 'Tunnel5025', '131']],
[['3'], ['7']]]
inter = info[0]
alive = info[1]
for line in inter:
int_index = line[0]
interface = line[1]
cat = line[2]
if cat == "131":
print(int_index, interface)
print(alive)
Re: Mehrdimensionales Array abfragen
Verfasst: Freitag 4. September 2015, 11:18
von Kebap
trumm hat geschrieben:
Mit der interaktiven Shell das hab ich verstenden nur auf die schnelle keine gefunden. Ich hab mir jetzt so eine Python für Windows installiert, aber damit komme ich gerade nicht so zurecht, der will nicht mal ein print ausführen.
Die Shell ist bei jeder Python Version automatisch dabei. Öffne mal deine Windows Shell und tippe "python"
Print verhält sich etwas anders in Python 2 und Python 3. Vielleicht hast du eine Version installiert, die nicht zu deiner Anleitung passt. Lässt sich aber leicht beheben.
Re: Mehrdimensionales Array abfragen
Verfasst: Freitag 4. September 2015, 13:02
von Hyperion
trumm hat geschrieben:Die Liste kommt aus einer snmp Abfrage eines Cisco Switches.
Ist das JSON? Oder kommt da tatsächlich eine Python-Datenstruktur "zurück"?
(Letztlich) Unabhängig davon woher das kommt, kann man es dennoch so umbauen, dass man intern damit komfortabler zum Ziel kommt. Und imho sollte man das auch.
Ohne die Grundlagen von Python zu lernen - und dazu gehören die grundlegenden Datenstrukturen wie Listen, Dictionaries und Sets - wirst Du letztlich nicht alleine zum Ziel kommen fürchte ich.
Hier mal der Ansatz (die In[1] und Out[1]-Präfixe ignorieren, die stammen aus der Python-Shell iPython):
Code: Alles auswählen
In [3]: info[0]
Out[3]:
[['1', 'GigabitEthernet1', '6'],
['2', 'GigabitEthernet2', '6'],
['3', 'GigabitEthernet3', '6'],
['4', 'Null0', '1'],
['5', 'Loopback10', '24'],
['6', 'Tunnel25', '131'],
['7', 'Tunnel5025', '131']]
In [4]: info[1]
Out[4]: [['3'], ['7']]
In [5]: from itertools import chain
In [6]: ids = set(chain.from_iterable(info[1]))
In [7]: ids
Out[7]: {'3', '7'}
In [8]: info[0][0][0]
Out[8]: '1'
In [9]: info[0][0][0] in ids
Out[9]: False
In [10]: for element in info[0]:
...: print("{} {}".format(element[0], element[0] in ids))
...:
1 False
2 False
3 True
4 False
5 False
6 False
7 True
Grundlegende Idee ist es, deine IDs (?) des zweiten Listenteils in ein Set zu bekommen [6] und dann mittels ``in`` Operator zu prüfen, ob eine Id aus der ersten Liste in der zweiten enthalten ist [9].
Re: Mehrdimensionales Array abfragen
Verfasst: Freitag 4. September 2015, 13:16
von trumm
Hallo Hyperion,
ich hab ja vor Python zu lernen, meine Lektüre liegt an der arbeit auch schon auf dem Tisch, doch beschäftige ich mich eben erst seit zwei Tagen damit

Ich bin aktuell soweit, das ich die DAten aus Info gesplittet habe einfach in zwei neue
Jetzt bäuchte ich nur noch eine/zwei for Schleifen die prüfen ist es Type/Cat inter[2] = 131 ist
Wenn JA
Prüfe ob ob Interface_Index inter[0] in alive irgendwo enthalten ist
Wenn Ja = Ok
Else Nein = Kaputt
So grob stelle ich mir das vor.
Re: Mehrdimensionales Array abfragen
Verfasst: Freitag 4. September 2015, 13:20
von Hyperion
Den ersten Teil hat Dir doch schon /me gezeigt und den zweiten ich

Re: Mehrdimensionales Array abfragen
Verfasst: Freitag 4. September 2015, 14:50
von trumm
Geht nicht sowas wie
Code: Alles auswählen
for int_index, interface, cat in info[0]:
if cat == '131' in info[0]:
if int_index in info[1]:
print(Ok)
else:
print(Kaputt)
print(Keine Ahnung)
Ich verstehe das imemr noch nicht

Re: Mehrdimensionales Array abfragen
Verfasst: Freitag 4. September 2015, 15:03
von /me
info[1] sieht wie folgt aus
Du hast eine Liste mit zwei Elementen. Das erste Element ist eine Liste mit dem Element '3', das zweite eine Liste mit dem Element '7'. Das heißt nichts anderes, als dass '3' nicht in info[1] enthalten ist (['3'] hingegen ist enthalten).
int_index in info[1] kann also niemals wahr sein wenn
int_index ein String ist.
Das einfachste ist es folglich eine simple Datenstruktur zu erstellen die alle Werte der inneren Listen enthält und schnell getestet werden kann. Dafür hat Hyperion ein Beispiel geliefert.
Jetzt musst du nur noch das kaputte
if cat == '131' in info[0] reparieren.
Re: Mehrdimensionales Array abfragen
Verfasst: Freitag 4. September 2015, 15:20
von trumm
DANKE! Euch allen, deswegen kann ich das nicht vergleiche. Jetzt fällt langsam Licht ins dunkle Zimmer
Aktuell habe ich das jetzt so abgeschrieben
Code: Alles auswählen
def check_mist(item, _no_params, info):
from itertools import chain
ids = set(chain.from_iterable(info[1]))
for int_index, interface, cat in info[0]:
if cat == "131":
if int_index in ids:
return (0, "OK")
else:
return (2, "Not found")
Was ich am
cat reparieren soll erschliesst mich mir noch nicht, genauso wenig warum immer noch ein "Not Found" ergibt.
Muss ich die
cat auch noch irgendiwe umwandeln in etwas für "lesbares" ? Vielleicht sogar genauso ?
Ich wünsche mir heute noch ein Erfolgserlebnis zum Wochenende. Ist crazy, ich bastele den ganzen Tag und ich vermute viele von euch hätten das in 5 Minuten fertig
Danke nochmals
Re: Mehrdimensionales Array abfragen
Verfasst: Freitag 4. September 2015, 15:30
von Hyperion
Lasse Dir die Inhalte der Namen in der Schleife einfach mal ausgeben. Dann siehst Du, was *wirklich* darin steht. Damit kann man dann oftmals schlussfolgern, wieso es noch ein Problem gibt.
Du hast übrigens meine Fragen nach der Herkunft der Daten noch nicht beantwortet

(Also wie Du dieses Datenformat bekommst!)
Re: Mehrdimensionales Array abfragen
Verfasst: Freitag 4. September 2015, 15:34
von trumm
Entschulige, das war nicht meine Absicht

Also die Daten kommen von einem Cisco - Switch die per SNMP abgefragt werden, die Dinger sind echt einfachter zu Konfigurieren, als mit Python Wert, Zahlen Strings zu vergleichen
Ich komme jetzt zumindest an den Punkt, das er die 131 frisst, aber in der unteren Schleife komme ich nicht zurecht.
Er findet die info[0] und ids Werte nicht

Re: Mehrdimensionales Array abfragen
Verfasst: Freitag 4. September 2015, 15:40
von Hyperion
trumm hat geschrieben:
Also die Daten kommen von einem Cisco - Switch die per SNMP abgefragt werden, die Dinger sind echt einfachter zu Konfigurieren, als mit Python Wert, Zahlen Strings zu vergleichen
Das hattest Du schon gesagt. Woher kommt aber *konkret* diese Python-Datenstruktur? Ganz platt formuliert: Wie kommt der Inhalt von ``info`` in Deinen Quellcode?
trumm hat geschrieben:
Ich komme jetzt zumindest an den Punkt, das er die 131 frisst, aber in der unteren Schleife komme ich nicht zurecht.
Er findet die info[0] und ids Werte nicht

Was ist die untere Schleife? Ich sehe da nur *eine* Schleife‽
Gehe Schritt für Schritt durch. Was hat welcher Name in welchem Durchlauf für einen Wert. Lass Dir alles mittels ``print`` ausgeben. Dann überlege, welche Bedingung nicht eingetreten ist und wieso das der Fall sein muss.
Re: Mehrdimensionales Array abfragen
Verfasst: Freitag 4. September 2015, 15:46
von trumm
Naja das ganze Teil ist für Nagios, Check-MK und so sieht es aus :
Code: Alles auswählen
#!/usr/bin/python
# -*- encoding: utf-8; py-indent-offset: 4 -*-
def inventory_mist(info):
#print(info)
#import pprint ; pprint.pprint(info)
for int_index, interface, cat in info[0]:
if cat == '131':
yield interface, None
def check_mist(item, _no_params, info):
from itertools import chain
inter = info[0]
alive = info[1]
print(inter)
ids = set(chain.from_iterable(alive))
for element in inter:
print(element)
if element[2] == '131':
if element[0] in ids:
return (0, "OK")
else:
return (2, "Not found")
return (3, "UNKNOWN - not yet implemented")
mist_info = [
( ".1.3.6.1.2.1.2.2.1", ["1", "2", "3"]
),
( ".1.3.6.1.4.1.9.9.449.1.4.1.1", ["4"]
)
]
check_info["mist"] = {
"check_function" : check_mist,
"inventory_function" : inventory_mist,
"service_description" : "Status of %s",
"snmp_info" : mist_info
Ganz interessant finde ich gerade, das meine Schleife einen Teil "Verschluckt" Deswegen wird hier nichts grün.
Das habe ich auf der Konsole.
[['1', 'GigabitEthernet1', '6'], ['2', 'GigabitEthernet2', '6'], ['3', 'GigabitEthernet3', '6'], ['4', 'Null0', '1'], ['5', 'Loopback10', '24'], ['6', 'Tunnel25', '131'], ['7', 'Tunnel5025', '131']]
['1', 'GigabitEthernet1', '6']
['2', 'GigabitEthernet2', '6']
['3', 'GigabitEthernet3', '6']
['4', 'Null0', '1']
['5', 'Loopback10', '24']
['6', 'Tunnel25', '131']
Status of Tunnel25 CRIT - Not found
[['1', 'GigabitEthernet1', '6'], ['2', 'GigabitEthernet2', '6'], ['3', 'GigabitEthernet3', '6'], ['4', 'Null0', '1'], ['5', 'Loopback10', '24'], ['6', 'Tunnel25', '131'], ['7', 'Tunnel5025', '131']]
['1', 'GigabitEthernet1', '6']
['2', 'GigabitEthernet2', '6']
['3', 'GigabitEthernet3', '6']
['4', 'Null0', '1']
['5', 'Loopback10', '24']
['6', 'Tunnel25', '131']
Status of Tunnel5025 CRIT - Not found
Wie man ganz oben sieht, gibt es in der SNMP Abfrage der info einen index der mit 7 beginnt.
Später aber fehlt dieser dann auf einmal. Das macht mich ja jetzt ganz verrückt. Dummerweise ist die 7 normalerweise alive, die 6 down und die 3 wird aufgrund des Filters Ignoriert

Re: Mehrdimensionales Array abfragen
Verfasst: Freitag 4. September 2015, 16:00
von Hyperion
Irgend wie sehe ich immer noch nicht, *wie* ``info`` jetzt gefüllt wird
