Initieren von leerem Dict mit einer for schleife

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
sharky
User
Beiträge: 3
Registriert: Freitag 19. Dezember 2014, 15:50

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 !
Zuletzt geändert von Anonymous am Freitag 19. Dezember 2014, 23:21, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Code-Tags gesetzt.
Benutzeravatar
darktrym
User
Beiträge: 784
Registriert: Freitag 24. April 2009, 09:26

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.
„gcc finds bugs in Linux, NetBSD finds bugs in gcc.“[Michael Dexter, Systems 2008]
Bitbucket, Github
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.
sharky
User
Beiträge: 3
Registriert: Freitag 19. Dezember 2014, 15:50

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
Sirius3
User
Beiträge: 17754
Registriert: Sonntag 21. Oktober 2012, 17:20

@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 |?
sharky
User
Beiträge: 3
Registriert: Freitag 19. Dezember 2014, 15:50

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
Sirius3
User
Beiträge: 17754
Registriert: Sonntag 21. Oktober 2012, 17:20

@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
Antworten