String als JSON formatieren?

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
chpo7234
User
Beiträge: 35
Registriert: Dienstag 29. September 2015, 10:19

Hallo Leute,

foglende Datei lese ich aus:
if type(define_hostgroups) != dict:
define_hostgroups = {}
define_hostgroups.update({'Group1': u'group1alias', 'Group2': u'group2alias'})
Nicht wundern, dass der Dateiinhalt in Python ist! Sie wird für ein anderes Programm verwendet und von diesem auch aktualisiert.
Für mich sind nur die beiden Wörter "Group1" und "Group2" wichtig.
Ich habe mir die Zeile zwischengespeichert und mittels split() das JSON-Format "ausgeschnitten":

Code: Alles auswählen

import json
fobj = open("opt/omd/sites/mysite/etc/check_mk/conf.d/wato/groups.mk")
for line in fobj:
    if "define_hostgroups.update" in line:
        lineList = line.split("define_hostgroups.update(")
        jsonString = lineList[1].split(")")
        break
fobj.close()
Klar, paar Exceptions muss ich später noch ergänzen. Die Namen "Group1" und "Group2" sind variabel, sonst hätte ich in dem ober liegenden Code natürlich direkt nach "Group1" gesucht.

Jetzt habe ich folgendes versucht:

Code: Alles auswählen

jsonDumped = json.dumps(jsonString)
jsonLoads = json.loads(jsonDumped)
print jsonLoads[0]
Das gibt mir nun allerdings nur den gesamten String wieder. Hat hier jemand einen Vorschlag oder Tipps?

Lieben Gruß
Zuletzt geändert von chpo7234 am Donnerstag 8. Oktober 2015, 12:56, insgesamt 4-mal geändert.
Benutzeravatar
pillmuncher
User
Beiträge: 1484
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

chpo7234 hat geschrieben:Das gibt mir nun allerdings nur den gesamten String wieder.
Nein, tut es nicht. Du bekommst einen Syntaxfehler in der ersten Zeile. Und wenn du den richten würdest, noch einen am Ende. Poste bitte den tatsächlichen Code.

Außerdem ist die Idee, Python-Code zu generieren und diesen dann als Textdatei zu verwenden um Daten zu extrahieren, nun, sagen wir mal "interessant".
In specifications, Murphy's Law supersedes Ohm's.
chpo7234
User
Beiträge: 35
Registriert: Dienstag 29. September 2015, 10:19

Habe es nun mal korrigiert, sorry!

Hast du vielleicht einen Vorschlag, wie ich nun "Group1" und "Group2" extrahieren kann, bzw. wie ich das richtig in JSON umwandle und auf einzelne Elemente davon zugreifen kann? Es können natürlich auch mehrere "Groups" angefügt werden.

Ich brauche nun mal die Gruppen-Namen und ich weiß so keinen anderen Weg, als die mir vorliegende Python-Datei auszuwerten...
Sirius3
User
Beiträge: 17749
Registriert: Sonntag 21. Oktober 2012, 17:20

@chpo7234: wenn Du die Group-Aliases in mehreren Programmen brauchst, würde ich sie ja in ein Modul herausziehen und einfach importieren. Oder in eine Datei im JSON-Format auslagern. Python-Code zu parsen, ist eine ganz schlechte Idee.
Benutzeravatar
pillmuncher
User
Beiträge: 1484
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

chpo7234 hat geschrieben:Ich brauche nun mal die Gruppen-Namen und ich weiß so keinen anderen Weg, als die mir vorliegende Python-Datei auszuwerten...
Wenn du etwas mehr Kontext liefern ürdest, könnte man wahrscheinlich einen etwas weniger kuriosen Weg finden, dein Problem zu lösen. Übrigens ist dein Problem nicht "wie kann ich Python-Quelltext so zerlegen, dass am Ende ein JSON String herauskommt" sondern "Wie kann ich aus einem Programm Daten so generieren, dass ein anderes Programm damit arbeiten kann".

Damit ergibt sich die Frage, ob es unter deiner Kontrolle steht, wie die Python-Datei, die du analysieren willst, generiert wird?

Wenn ja, dann schlage ich vor, du erzeugst statt dessen einfach eine Konfigurationsdatei (zB. JSON), in die du die Gruppendaten schreibst. Statt ein Programm zu generieren, schreibst du einfach eines von Hand, das diese Konfigurationsdatei einliest und die Daten daraus verwendet. Genauso verfährst du dann bei dem Programm, das du gerade schreiben möchtest.

Wenn nein, würde ich vielleicht das ast-Modul aus der Standard-Bibliothek verwenden, statt selber Source-Code zu parsen. Auch um das zu entscheiden, benötigt man mehr Kontext. Ist das generierte Programm sehr klein? Ist der Teil, den du gezeigt hast, das einzige, was sich ändern kann?

Oder du folgst dem Vorschlag von Sirius3 und importierst das generierte Programm einfach.
In specifications, Murphy's Law supersedes Ohm's.
BlackJack

@chpo7234: Bei dem Quelltext den Du da auslesen möchtest ist das ``if type(define_hostgroups) != dict:`` auch reichlich komisch. Ein Name sollte immer nur an *einen* („Duck“-)Typ gebunden werden und damit solche Tests überflüssig machen. Wenn auf Typen testen dann nur auf besonderen wie `None`, wobei man da nicht auf den Typ testen muss weil der Wert ein Singleton ist und damit mit ``is`` oder ``is not`` direkt effizient verglichen werden kann, oder wenigstens mit `isinstance()` um auch abgeleitete Typen nicht unnötigerweise auszuschliessen.

Wenn Du Python robuster als mit simplemen Zeichenkettenoperationen parsen willst, gibt es das `ast`-Modul in der Standardbibliothek. Aber wie meine Vorredner schon gesagt haben: So etwas sollte man gar nicht erst machen müssen. Vermische keine Daten die an anderen Stellen auch benötigt werden mit Programmcode sondern speichere die separat.
chpo7234
User
Beiträge: 35
Registriert: Dienstag 29. September 2015, 10:19

Danke für deinen Beitrag, Sirius.

Leider bin ich noch nicht so fortgeschritten und verstehe nicht direkt, wie ich das anstellen kann mit dem Modul-Importierung und der JSON-Auslagerung.

Meinst du, ich kann in meinen Quellcode einfach schreiben:
"import opt/omd/sites/mysite/etc/check_mk/conf.d/wato/groups.mk ?"
Benutzeravatar
pillmuncher
User
Beiträge: 1484
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

@chpo7234: Arbeite mal das hier durch: https://py-tutorial-de.readthedocs.org/ ... dules.html. Oder gleich das ganze Tutorial. Es ist nicht übermäßig lang und die Grundlagen wirst du brauchen, wenn du in Python programmierst.
In specifications, Murphy's Law supersedes Ohm's.
chpo7234
User
Beiträge: 35
Registriert: Dienstag 29. September 2015, 10:19

Vielen Dank für die viele Hilfsbereitschaft und tut mir leid, dass ich immer so verzögert reagiere. Ausschließlich die Inhalte dieses Forums benötigen immer EWIG Zeit bis sie geladen haben. Leider ist das nur auf der Arbeit der Fall..
Damit ergibt sich die Frage, ob es unter deiner Kontrolle steht, wie die Python-Datei, die du analysieren willst, generiert wird?
Nein, das steht nicht in meiner Kontrolle. Die wird von einem Programm (WATO) generiert, welches ich nicht selbst geschrieben habe.
Ist der Teil, den du gezeigt hast, das einzige, was sich ändern kann?
Nein, leider nicht. Da können noch einige Zeilen mehr entstehen. Falls diese Zeilen von Relevanz sein sollten, werde ich später noch ein umfangreicheres Beispiel ergänzen.
Vermische keine Daten die an anderen Stellen auch benötigt werden mit Programmcode sondern speichere die separat.
Ich habe ja leider keinen Einfluss darauf, wie das andere Programm die Gruppen speichert.. :/

Ich werde mich denn mal mit dem ast-Modul auseinander setzen und mir den Link von pillmuncher zu Herzen nehmen. Danke dafür!
BlackJack

Zumindest aus dem gezeigten Quelltextschnippsel bekomme ich so das Argument vom `define_hostgroups.update()`-Aufruf als Wörterbuch was sich dann einfach als JSON speichern lässt:

Code: Alles auswählen

import ast


SOURCE = '''\
if type(define_hostgroups) != dict:
    define_hostgroups = {}
    define_hostgroups.update({'Group1': u'group1alias', 'Group2': u'group2alias'})
'''

class Visitor(ast.NodeVisitor):

    def __init__(self):
        ast.NodeVisitor.__init__(self)
        self.result = None

    def visit_Call(self, call):
        if not isinstance(call.func, ast.Attribute):
            return
        attribute = call.func
        if not isinstance(attribute.value, ast.Name):
            return
        name = attribute.value
        if name.id == 'define_hostgroups' and attribute.attr == 'update':
            self.result = ast.literal_eval(call.args[0])


def main():
    visitor = Visitor()
    visitor.visit(ast.parse(SOURCE))
    print visitor.result


if __name__ == '__main__':
    main()
Antworten