Serverliste importieren und abarbeiten

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.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Ok, dann schlage ich mal folgende JSON-Datei vor:

Code: Alles auswählen

{
    "yz": [
        {
            "ip": "noch ne ip", 
            "user": "noche einer", 
            "path": "wieder einer"
        }
    ], 
    "xy": [
        {
            "ip": "ip-adresse", 
            "user": "user1", 
            "path": "path1"
        }, 
        {
            "ip": "noch ne ip", 
            "user": "user99", 
            "path": "path56"
        }
    ]
}
Letztlich hast Du ein Dict, in welchem nach den Stati ("xy" und "yz") unterschiedliche Listen zugerodnet sind. Innerhalb der Listen habe ich hier wieder ein Dict gewählt, wenn es wirklich immer nur "ip", "user" und "path" in einer festen Reiehnfolge sind, kann man da auch eine Liste nehmen.

Das ganze könnte man so abarbeiten:

Code: Alles auswählen

import json

# Exception Handling überlasse ich mal Dir ;-)
with open("jobs.json", "r") as in_file:
    jobs = json.load(in_file)

try:
    for job in jobs[user_eingabe]:
        print "Job: {ip}, {user}, {path}".format(**job)
        process(job)
except KeyError, e:
    print "Ungültiger / Undefinierter Status"
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Zu Deinem Code:

- Zeilen > 80 Zeichen ([wiki]Lange Zeilen im Sourcecode)[/wiki]
- Wieso verwendest Du os.system, wo Du doch weiter oben subprocess nutzt?
- Code auf Modulebene ist nicht wirklich toll
- Strings besser nicht mit "+" zusammensetzen
- für das Zusammensetzen von Pfaden gibt es os.join
morytox
User
Beiträge: 25
Registriert: Dienstag 15. September 2009, 13:17

- was bedeutet code auf modulebene ?
- subprocess fand ich nciht so gut , ich hatte es anfangs mit subprocess versucht hab aber nur fehler bekommen weil da so viele ergänzungeen und alles war , hab einfahc nicht durchgesehn und os.system sieht verdammt einfach aus bzw. war für mich sehr einfach anzuwenden
-zeiln kannsch kürzen da hast recht
-wieso nicht + ? soll ich in dem fall dann os.system(os.join("string", var, "string")) schreiben ?

*edit*

wo kommen jetzt eigentlich die Auszuführenden Funktionen hin und was muss ich als parameter übergeben ...
*hmz* klar bei process ^^

print "Job: {ip}, {user}, {path}".format(**job) wofür ist das noch gleich gut ?

und wenn man jetzt den prozess mit dem parameter ausführt hat man in der funktion die 3 variablen ip usr und path mit den zugehörigen daten belegt ja ?
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

morytox hat geschrieben:- was bedeutet code auf modulebene ?
Beispiel:

Code: Alles auswählen

print "Hallo Welt"

def func():
    #mache etwas


def func2():
    # mache was anderes

...
Das print steht hier auf Modulebene. Wenn Du nun dieses Script (wir nennen es mal foo.py) in ein anderes Python-Script einbinden willst, würdest Du folgendes schreiben:

Code: Alles auswählen

import foo

def bar():
    foo.func2()
Du willst also in der Funktion bar die Funktion func2 aus dem Script (Modul) "foo.py" nutzen. Nun passiert nach dem import aber folgendes: Es werden alle Befehle abgearbeitet in foo, die sich auf Modulebene (sprich außerhalb von Funktionen und Klassen) befinden. Du würdest also die Ausgabe des print Befehls sehen. Das ist aber in diesem Falle vermutlich nicht erwünscht.

Also nutzt man folgenden Trick:

Code: Alles auswählen

import irgendwas

def func1():
    pass


def funcx():
    pass


def main():
    # hier ist der Einstiegspunkt in die Abarbeitung des Scriptes
    print "Hallo Welt!"
    func1()
    ...

if __name__ == "__main__":
    main()
Startest Du dieses Script, so "merkt" der Interpreter, dass Du dieses Script ausfürehn möchtest und verzweigt in die main()-Funktion (Kann auch anders heißen oder direkt unterhalb des if __name__-Hooks stehen).

Importierst Du nun dieses Script in einem anderen, so weiß der Interpreter, dass er eben nicht in dieses main()-Funktion reinrutschen soll. Genau das erwartet man eben bei dieser Benutzung.

Ein weiterer Grund ist die Vermeidung von unnötigen globalen Variablen. Schreibst Du alles "planlos" auf Modulebene, so sind natürlich alle Namen in allen Funktionen verfügbar. Das ist idR gefährlich und unnötig. So kannst Du Dir überlegen, was Du ggf. in der main()-Funktion definierst und was nicht.
- subprocess fand ich nciht so gut , ich hatte es anfangs mit subprocess versucht hab aber nur fehler bekommen weil da so viele ergänzungeen und alles war , hab einfahc nicht durchgesehn und os.system sieht verdammt einfach aus bzw. war für mich sehr einfach anzuwenden
Was genau hat denn da nicht funktioniert? Man wird Dir hier immer aus guten Gründen zu subprocess raten. Es ersetzt eben das alte Sammelsurium an verschiedenen Funktionen (popen, popen2, usw) durch eine Abstraktion. Also: Auf subprocess umstellen lohnt sich.
-wieso nicht + ? soll ich in dem fall dann os.system(os.join("string", var, "string")) schreiben ?
Strings sind immutable in Python, d.h. man kann diese Zeichenketten nicht verändern. "foo" + "bar" erzeugt in Wirklichkeit also eine neue Zeichenkette. Das ist für Laufzeit und Ressourcen nicht förderlich. Man kann einzelne Zeichenketten z.B. durch "".join() zusammenfügen.

Code: Alles auswählen

"".join(["foo", "bar"])
Man beachte die "[" und "]". join() verlangt als Parameter eine Sequenz.

Und ja, genauso sollte man os.join() verwenden. Damit hast Du einen garantiert fehlerfreien Pfad.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Ich habe mein Snippet mal überarbeitet und kommentiert.

Code: Alles auswählen

import json

# Exception Handling überlasse ich mal Dir ;-)
with open("jobs.json", "r") as in_file:
    jobs = json.load(in_file)

try:
    for job in jobs[user_eingabe]:
        # dient nur zur Ausgabe des Jobs
        print "Job: {ip}, {user}, {path}".format(**job)
        # hier rufst Du eben die Funktion(en) auf, die mit diesen Parametern
        # abgearbeitet werden sollen.
        # das "**" vor job erkläre ich unten, Du kannst aber auch direkt die
        # Parameter übergeben, also job["ip"] z.B.
        process(**job)
except KeyError, e:
    print "Ungültiger / Undefinierter Status" 
Das "**job" ist eine gute Idee, wenn die Funktion eben genau diese Parameter erwartet, oder beliebige Parameter annehmen soll. Damit wird das Dict quasi direkt als Parameter in die Funktion übergeben.

Code: Alles auswählen

In [23]: foo(**jobs)
{'ip': '192.168.0.1', 'user': 'chris'}

In [24]: def foo(**kwargs):
   ....:     print kwargs
   ....:
   ....:

In [25]: jobs = {"ip": "192.168.0.1", "user": "chris"}

In [26]: foo(**jobs)
{'ip': '192.168.0.1', 'user': 'chris'}

In [31]: def bar(user, ip):
   ....:     print user, ip
   ....:
   ....:

In [32]: bar(**jobs)
chris 192.168.0.1
morytox
User
Beiträge: 25
Registriert: Dienstag 15. September 2009, 13:17

hab ich das jetzt richtig eingebettet ? So dass er mir in den Funktionen die benötigten variablen abarbeitet ? (Hab in der json datei die ich serverconfig genannt hab 2 teile zu einem zusammengefügt weil ich es eig. nur in der verbindung brauch und es n bissel einfacher gestaltet, somit ist server jetzt usr@ip in der kombo kann ich es nur verwenden)
*edit* oops vergessen parameter zu übergeben : geändert

Code: Alles auswählen

with open("serverconfig.json", "r") as in_file:
    jobs = json.load(in_file)
try:
    for job in jobs[user_eingabe]:
        print "Job: {server}, {path}".format(**job)
        if "zu" in upjs:
            cleanupjs()
            cleanupwsjs(**job)
            exportjs()
            packenjs()
            uploadjs(**job)
            detarjs(**job)
            logging.info("WebApp_JS_Skripts"+standn+server)
        else:
            logging.info("WebApp_JS_Skripts"+stand+server)
     logging.info("Deployment durchgeführt")
except KeyError, e:
    print "Ungültiger / Undefinierter Status"
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Wieso probierst Du es nicht einfach aus? ;-)

Ich weiß nicht, was "zu" ist und was "upjs" ist. Also kann ich dazu nichts sagen. Wozu ist dieses if-Konstrukt da?

Prinzipiell sieht es schon mal richtig aus.

Hast Du es denn nicht einmal ohne diese Server-Aufrufe getestet? Ist doch erst einmal das ideale Vorgehen...

Edit: Wenn Du mal wieder einen längeren Code postest, ist es eine gute Idee den in einen paste-Container auszulagern; hier sehr beliebt ist paste.pocoo.org :-)
morytox
User
Beiträge: 25
Registriert: Dienstag 15. September 2009, 13:17

vorerst letzte frage: auf die user_eingabe die du erwähnt hattest habe ich jetzt einen raw_input gelegt der dann die zeichenkette enthält die ich in der json datei als zuordnung festgelegt habe. ist das richtig ?

File "deploymentasl.py", line 111
with open("serverconfig.json", "r") as in_file:

invalid syntax <-- das spuckt er mir beim test erstmal als fehler aus ...
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

morytox hat geschrieben:vorerst letzte frage: auf die user_eingabe die du erwähnt hattest habe ich jetzt einen raw_input gelegt der dann die zeichenkette enthält die ich in der json datei als zuordnung festgelegt habe. ist das richtig ?
z.B. das, genau. Kommt aber ja drauf an, wenn ich eine GUI habe, dann wird das ganze ja eher aus einem Eingabefeld kommen ;-)
File "deploymentasl.py", line 111
with open("serverconfig.json", "r") as in_file:

invalid syntax <-- das spuckt er mir beim test erstmal als fehler aus ...
Welche Python-Version nutzt Du? Wenn es 2.5 sein sollte, brauchst Du iirc noch ein

Code: Alles auswählen

from future import with
Edit:
Ich würde um das Einlesen der JSON-Datei aber noch eine Exception abfangen:

Code: Alles auswählen

try:
    with open()...
except IOError, e:
    print e
else:
    # hier dann das weitere
morytox
User
Beiträge: 25
Registriert: Dienstag 15. September 2009, 13:17

ich habe 2.4.x version auf meim Linux die aktuelle 3er version für linux müsst ich erstmal kompilieren, darauf hatte ich bisher kein bock...
import hat nix gebracht gleicher fehler
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

morytox hat geschrieben:ich habe 2.4.x version auf meim Linux die aktuelle 3er version für linux müsst ich erstmal kompilieren, darauf hatte ich bisher kein bock...
import hat nix gebracht gleicher fehler
Ok, das erklärt es ;-)

In der 2.4 gibt es kein with-Statement.

Code: Alles auswählen

try:
    in_file = open("name", "r")
    jobs = json.read()
except IOError, e:
    print e
else:
    # deine Funktionalität
finally:
    in_file.close()
Zusätzlich brauchst Du dann ein externes JSON-Modul, z.B.:
http://pypi.python.org/pypi/simplejson/

Doku dazu hier:
http://simplejson.googlecode.com/svn/ta ... index.html

Ich würde aber mal gucken, ob Du nicht auf eine 2.6er updaten kannst. 3.x ist def. noch nicht notwendig, aber für eine 2.4er würde ich nicht mehr wirklich entwickeln wollen.
morytox
User
Beiträge: 25
Registriert: Dienstag 15. September 2009, 13:17

hab das ma so umgewandelt, aber bei meine funktionalität habe ich das noch das was vorher vor den funktionen stand. Hab ich das richtig verstanden dass ich das jetzt wie folgt schreiben muss ?:

Code: Alles auswählen

try:
    in_file = open("serverconfig.json", "r")
    jobs = json.read()
except IOError, e:
    print e
else:
    for job in jobs[user_eingabe]:
        print "Job: {server}, {path}".format(**job)
        if "zu" in upjs:
            cleanupjs()
            cleanupwsjs(**job)
            exportjs()
            packenjs()
            uploadjs(**job)
            detarjs(**job)
            logging.info("WebApp_JS_Skripts"+standn+server)
        else:
            logging.info("WebApp_JS_Skripts"+stand+server)
except KeyError, e:
    print "Ungültiger / Undefinierter Status"
finally:
    in_file.close()
logging.info("Deployment durchgeführt")
logging.shutdown()
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

morytox hat geschrieben:hab das ma so umgewandelt, aber bei meine funktionalität habe ich das noch das was vorher vor den funktionen stand. Hab ich das richtig verstanden dass ich das jetzt wie folgt schreiben muss ?:
Nee, so stimmt die Einrückung nicht und Du fängst einen KeyError ab, der nicht von den Zeilen 2+ 3 auisgelöst werden kann. Du willst den in Zeile 7 abfangen!

So sollte es tun:

Code: Alles auswählen

try:
    in_file = open("serverconfig.json", "r")
    jobs = json.read()
except IOError, e:
    print e
else:
    try:
    # ab hier alles noch mal einrücken
    for job in jobs[user_eingabe]:
        print "Job: {server}, {path}".format(**job)
        if "zu" in upjs:
            cleanupjs()
            cleanupwsjs(**job)
            exportjs()
            packenjs()
            uploadjs(**job)
            detarjs(**job)
            logging.info("WebApp_JS_Skripts"+standn+server)
        else:
            logging.info("WebApp_JS_Skripts"+stand+server)
    # ab hier stimmt die EInrückung wieder
    except KeyError, e:
        print "Ungültiger / Undefinierter Status"
finally:
    in_file.close()
# stimmt hier ja gar nicht - imho muss das doch nur bei einem Erfolgsfall
# gemacht werden!
logging.info("Deployment durchgeführt")
# das wäre hier ok
logging.shutdown()
Ich würde Dir dringend mal raten, das Tutorial durchzuarbeiten. Du scheinst bei vielem noch Verständnislücken zu haben.

Desweiteren solltest Du Dir angewöhnen kleine Häppchen zu testen. "Wir" arbeiten schon seit 2 Stunden an dem Problem und Du hast vermutlich nicht einmal gestest, ob Du diese JSON-Datei überhaupt lesen kann!?! Hast Du denn schon ein JSON-Modul installiert?

Wieso testest Du nicht erst einmal den Script-Rumpf ohne die Server-Aufrufe. Dann würdest Du doch schnell sehen, was klappt und an welcher Stelle was stehen muss!
morytox
User
Beiträge: 25
Registriert: Dienstag 15. September 2009, 13:17

hmpf.. joa .. hmm
ma kurz zu meiner lage ... bin Azubi in der 3. Woche und grad dabei Scripten zu lernen mit python , der sprache die ich 4 jahre in der schule hatte aber sone themen wie hier nie angerissen wurden ( zudem isses auch ne ganze zeit her) , zudem muss ich hier mit linux komplett arbeiten was für mich auch n kompletter neueinstieg ist ... nun hatt ich auch noch ne endlose diskussion über das json format , für welches ich jetzt extra module installieren muss und meine sag ich ma vorgesetzten fidnen das nich so toll da das script später auch auf anderen umgebungen laufen muss und man da nicht noch extra module geladen werden sollen... -.-*
kann man auch ne möglichkeit mit csv datein realisieren weil die wohl überall laufen sollen...
also wie die aufgebaut ist wurde mir grad erklärt aber da hier niemand in python programmiert kann mir niemand sagen wie ich das dann umsetze
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Ich habe JSON ja nur als eine von vielen Möglichkeiten vorgeschlagen! Letztlich würde das in anderen Formaten ähnlich aussehen.

Ich wußte ja nicht, dass Du eine relativ alte Python Version nutzt. JSON ist ab 2.5 iirc in der Standard-Lib von Python dabei.

Natürlich kannst Du auch eine CSV-Datei nutzen:

Code: Alles auswählen

xy, user@192.168.0.1
xy, ich@du.de
yz, "sons was
Hierbei hast Du natürlich das Problem, dass Du darauf achten musst, welche Delimiter Du nimmst, damit es zu keinen Konflikten mit den Daten kommt.

Schau Dir einfach mal das CSV-Modul in der Doku an.

Hast Du denn evtl. mal nachgefragt, ob man nicht einfach Python 2.6 installieren kann? Je nach Linux-Distro sollte es da doch Pakete für geben! Was nutzt ihr denn?
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Bitte versuch den Text verstaendlich zu schreiben und zu formattieren.

simplejson gibt es auch als pure Python, das kannst du einfach mit dem Skript verteilen.
Als CSV ist das natuerlich auch moeglich, du musst allerdings erst mal die Datenstruktur wieder herstellen, um einen so konfortablen Algorithmus wie bei Hyperion zu haben.
Die Alternative waere uebrigens 2 Dateien fuer die 2 Gruppen zu benutzen, um das Einlesen zu vereinfachen (Bei JSON braucht man das nicht).
morytox
User
Beiträge: 25
Registriert: Dienstag 15. September 2009, 13:17

installieren des neuen progs ist ungünstig , einfach zu viele server ... und das nur zu übungszwecken ... später soll ich das alles dann in pearl und bash portieren und damit weiterlernen, das ganze ist für mich nur auf python aufgezogen weil ich schon vorwissen mitbringe , nur irgendwann soll ich auf den firmenstandart angepasst werden.

Die einzelnen Elemente trenn ich einfach mit ; da ich dann ja auch datein aus exel importieren kann ... ich probier einfach mal weiter rum jetzt einfach von klein nach groß und wenn ich doch nochmal dringende fragen hab (fr. oder nxt week) schreib ich hier wieder ... müsst ja dann wieder oben sein das topic. Aber trotzdem schonmal ganz vielen dank für die umfangreiche hilfe bisher !
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

@Cofi: Naja, da es anscheinend nicht so auf Redundanz ankommt, wäre das Format ja einfach so flach wie ursprünglich vorgestellt:

Code: Alles auswählen

xy, user@192.168.0.1
xy, ich@du.de
yz, user@192.168.0.1
yz, sonst was
Ohne Aussagen zur Anzahl an Jobs und wie die Liste eigentlich erstellt wird, kann man sich da schlecht gegen CSV aussprechen. (Außer dass ich den fehlenden Unicode-Support ätzend finde und deswegen meist nicht auf CSV setze)

ok, man muss das Dict erst mal wieder aufbauen, aber in dem Falle geht das ja halbwegs einfach.

@morytox:
Hier wäre mal ein Ansatz mit CSV:

Code: Alles auswählen

import csv
from collections import defaultdict

stati = ["xy", "yz"]

try:
    jobs = defaultdict(list).fromkeys(stati)
    in_file = open("name", "r")
    for row in csv.reader(in_file):
        if row[0] in stati:
            jobs[row[0]]=row[1:]
except IOError, e:
    print e
else:
    # ab hier sollte es gehen wie gehabt.
finally:
    in_file.close()
Edit: Ich sehe grad, dass ich die Path-Angabe oben nicht berücksichtigt habe. Aber das ist ja einfach nur eine Spalte mehr. Allerdings ist die Struktur eines Jobs nun eine Liste und kein dict mehr. Also aufpassen bei der Parameterübergabe ;-)
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

morytox hat geschrieben:installieren des neuen progs ist ungünstig , einfach zu viele server ... und das nur zu übungszwecken ... später soll ich das alles dann in pearl und bash portieren und damit weiterlernen, das ganze ist für mich nur auf python aufgezogen weil ich schon vorwissen mitbringe , nur irgendwann soll ich auf den firmenstandard angepasst werden.
Hm... naja, muss ja Dein Ausbilder wissen. Ich würde dann ja Python "vergessen" und mich sofort intensiv mit den obigen Sprachen befassen.

Dass Dein Ausbilder JSON wohl nicht kennt ist natürlich nen Armutszeugnis :-D
morytox
User
Beiträge: 25
Registriert: Dienstag 15. September 2009, 13:17

is das auch gängig in der 2.4 er variante ?
1. finally wollte er in dem zusammenhang nicht nehmen --> nachgelesen und es wurde geschrieben dass es erst ab 2.5 in der konstellation geht. sonst gibt es nur try:, exept, else oder try finally

und 2. wollt ich defaultdict importieren aber er findet es nicht
Antworten