Seite 1 von 1

Initieren von leerem Dict mit einer for schleife

Verfasst: Freitag 19. Dezember 2014, 23:09
von sharky
Hallo Pythonfreunde,

ich versuche eine Datenstruktur mit Dictonaries zu erstellen und komme stehe immer wieder vor dem gleichen Problem.

Ich möchte eine Datenstruktur erzeugen die folgendermaßen aussieht.

Code: Alles auswählen

{system1: {checks: {check_1 : ''" check_2 :  '', system_2: |{checks:{check_4: {....}, check_3:{....}}}
Nach etwas rum spielen, habe ich das auch hinbekommen, aber ich benötige dafür sehr viel wiederkehrenden Code.

Hier das Problem:

Code: Alles auswählen

for checks in parser.sections() :
		if checks.startswith('check'):	
			x = parser.items(checks)
			systems =  x[2][1].split(',')
			for system in systems:
				checks_dict[system]['checks'] =  checks_dict.get('check',{})
                                checks_dict[system]['checks'][attribute_names] =  checks_dict.get(attribute_names, attribute_value)


Mein Problem dabei ist nun das wenn die Schleife einmal durchlaufen wird, wird das Dict wieder durch ein leeres Dict ersetzt. Das möchte ich natürlich verhindern. Muss ich das wirklich mit einer if Abfrage abfangen oder gibt es für sowas eine builin Funktion ?

Vielen Dank, Sharky !

Re: Initieren von leerem Dict mit einer for schleife

Verfasst: Freitag 19. Dezember 2014, 23:30
von darktrym
Ich versteh nicht was du willst(oder es ist zu spät für mein Hirn). So wie das formulierst überschreibst du stets die Werte.

Re: Initieren von leerem Dict mit einer for schleife

Verfasst: Freitag 19. Dezember 2014, 23:46
von BlackJack
@sharky: Zeile 6 ist das Problem denn wenn das Wörterbuch keinen 'check'-Schlüssel hat, wird da natürlich jedes mal ein leeres Wörterbuch erzeugt. Im anderen Fall, wenn es einen solchen Schlüssel gibt, dann wird da immer wieder der Wert zu diesem Schlüssel zugewiesen. Das erscheint mir an der Stelle irgendwie sehr eigenartig. Kannst Du nicht vor diesen ganzen Schleifen einfach ein leeres Wörterbuch erzeugen und das dann nach den Schleifen unter 'checks' eintragen?

Wobei auch komisch ist das für jeden Wert von `system` das *selbe* Wörterbuch verwendet wird wenn es 'checks' gibt. Und natürlich darf kein `system` jemals den Wert 'check' annehmen, dann wird das total merkwürdig. Also noch merkwürdiger als das jetzt schon aussieht.

Re: Initieren von leerem Dict mit einer for schleife

Verfasst: Sonntag 21. Dezember 2014, 13:13
von sharky
BlackJack hat geschrieben:@sharky: Zeile 6 ist das Problem denn wenn das Wörterbuch keinen 'check'-Schlüssel hat, wird da natürlich jedes mal ein leeres Wörterbuch erzeugt. Im anderen Fall, wenn es einen solchen Schlüssel gibt, dann wird da immer wieder der Wert zu diesem Schlüssel zugewiesen.
Hi BlackJack, genau das ist mein Problem.

Von mir aus muss ich kein leeres Dict erzeugen, aber Python sieht das doch so vor, ansonsten erhält man doch einen KeyError.

Ich würde am liebsten sofort die Werte da rein schieben. Aber so wie ich das verstanden habe muss man doch erst ein Dict erzeugen . Bevor man anschließend Werte zuweist.

Gruß Sharky

Re: Initieren von leerem Dict mit einer for schleife

Verfasst: Sonntag 21. Dezember 2014, 14:17
von Sirius3
@sharky: Deine Frage versteh ich nicht, und BlackJack beschreibt nur, das was Dein Code tut, und will damit ausdrücken, dass der Code Sachen macht, die in allen mir denkbaren Anwendungsfällen keinen Sinn machen, aber vielleicht hast Du ja einen Anwendungsfall wo das doch sinnvoll ist.
Was ist parser? Was x[2][1]? Was sind attribute_names und attribute_values, warum wird immer das selbe in die Dictionaries geschrieben? Warum gibt es noch eine Zwischenschicht 'checks' die anscheinend immer nur aus diesem einen Schlüssel besteht? Wo wird checks_dict erzeugt? Und was ist das für eine seltsame Datenstruktur? Welche Bedeutung haben darin die Zeichen " und |?

Re: Initieren von leerem Dict mit einer for schleife

Verfasst: Sonntag 21. Dezember 2014, 14:39
von sharky
Hey Sirius,

ich hol besser etwas weiter aus.

Code: Alles auswählen

[system_1]
description=Server 1
address=10.113.96.1
port=161
communityro=blubb

[system_2]
description=Server 2
address=10.113.96.2
port=161
communityro=blubb

[check_1]
description=ifInOctets
oid=1.1.1.1.1.1.1.1.1.1.1.1
system=system_1,system_2

[check_2]
description=ifOutOctets
oid=2.2.2.2.2.2.2.2.2.2.2.2
system=system_2,system_3,system_4
Das möchte ich gern in ein Dict importieren.
Aktuell hat add_system keine Funktion, liegt aber nur daran, weil ich es nicht aufrufe.



Mein Ergebnis :

Code: Alles auswählen

{'system_2': {'checks': {'check_2': {'oid': '2.2.2.2.2.2.2.2.2.2.2.2', 'description': 'ifOutOctets'}, 'check_1': {'oid': '1.1.1.1.1.1.1.1.1.1.1.1', 'description': 'ifInOctets'}}}, 'system_3': {'checks': {'check_2': {'oid': '2.2.2.2.2.2.2.2.2.2.2.2', 'description': 'ifOutOctets'}}}, 'system_1': {'checks': {'check_1': {'oid': '1.1.1.1.1.1.1.1.1.1.1.1', 'description': 'ifInOctets'}}}, 'system_4': {'checks': {'check_2': {'oid': '2.2.2.2.2.2.2.2.2.2.2.2', 'description': 'ifOutOctets'}}}}
So sieht mein Programm aus.

Code: Alles auswählen

#!/usr/bin/python

from ConfigParser import SafeConfigParser

#systems = dict()


def read_ini():
	parser = SafeConfigParser()
	return parser#.read('systems.ini')

def add_systems(parser):
	dict_systems= dict()
	parser.read('systems.ini')
	for system in parser.sections() :
		if system.startswith('system'):
			dict_systems[system] = dict_systems.get(system, {})
			for attribute_names , attribute_value in parser.items(system):
				dict_systems[system][attribute_names] = dict_systems.get(attribute_names, attribute_value)
	
	#print dict_systems	
	return dict_systems	
def add_checks(parser,dict_systems): 	
	
	checks_dict = dict()
	systems_in_check = []
	# print dict_systems.keys()
	for checks in parser.sections() :
		if checks.startswith('check'):	
			x = parser.items(checks)
			systems =  x[2][1].split(',')
			for system in systems:
				checks_dict[system] = checks_dict.get(system, {})

	for checks in parser.sections() :
		if checks.startswith('check'):	
			x = parser.items(checks)
			systems =  x[2][1].split(',')
			for system in systems:
				checks_dict[system]['checks'] =  checks_dict.get('check',{})
	for checks in parser.sections() :
		if checks.startswith('check'):	
			x = parser.items(checks)
			systems =  x[2][1].split(',')
			for system in systems:
				checks_dict[system]['checks'][checks] =  checks_dict.get(checks, {})
	for checks in parser.sections() :
		if checks.startswith('check'):	
			x = parser.items(checks)
			systems =  x[2][1].split(',')
			for system in systems:
				for attribute_names, attribute_value in parser.items(checks):
					if attribute_names != 'system':
						checks_dict[system]['checks'][checks][attribute_names] =  checks_dict.get(attribute_names, attribute_value)



# {system1: {checks: {check_1 : ''
#					 check_2 :  ''}



x=read_ini()

#print add_systems(x)
#print add_systems(x).keys()
#print add_systems(x)
add_checks(x,add_systems(x))
So sieht mein Workaround aus zum erstellen dieser Datenstruktur. Das kann aber ja nicht die Lösung sein ;) . Ich hoffe es ist jetzt etwas deutlicher ? Im nächsten Schritt führe ich die zwei Dict's zusammen, aber eigentlich war es geplant direkt in Dict_systems zu schreiben.

Gruß Sharky

Re: Initieren von leerem Dict mit einer for schleife

Verfasst: Sonntag 21. Dezember 2014, 15:34
von Sirius3
@sharky: ich hoffe doch mal, es gibt nur jeweils eine Section mit dem selben Namen. Für die Konstruktion dict[key] = dict.get(key, value) gibt es die setdefault-Methode. Einrücktiefe sind 4 Leerzeichen und Leerzeilen sollten dort sein, wo es die Lesbarkeit erhöht, also insbesondere vor def-Zeilen und nicht danach. Eine Methode, die read_ini heißt, sollte das auch tun und nicht nur ein parser-Objekt erzeugen.
Was sind Deine wesentlichen Schritte:
1. Lesen der ini-Datei
2. Erzeugen der System-Dictionaries
3. Erzeugen der Check-Dictionaries
4. Zuordnen der Check-Dictionaries an die System-Dictionaries

Code: Alles auswählen

from ConfigParser import SafeConfigParser
 
def read_ini(filename):
    parser = SafeConfigParser()
    parser.read(filename)
    systems = {}
    for section in parser.sections():
        content = dict(parser.items(section))
        if section.startswith('system'):
            content['check'] = {}  # Zusaetzliches Feld fuer Checks
            systems[section] = content
        elif section.startswith('check'):
            for check_system in content['system'].split(','):
                systems[check_system]['check'][section] = content
    return systems