Umstellen von bash auf python?

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
carsten
User
Beiträge: 2
Registriert: Mittwoch 21. Juni 2006, 18:13

Hallo,

ich habe schon öfter von Python gehört und auch schon ein paar mal drüber nachgedacht, mich damit zu beschäftigen.
Jetzt stehe ich aber vor einem Problem für das es in der Bash scheinbar keine Lösung gibt und ich also eine Alternative brauche.
Wir machen derzeit recht viel mit der bash und für grafische Ausgaben nutzen wir kommander.
Ich muss nun aber in MySQL eine Tabelle sperren, einen Wert abfragen, diesen Wert verarbeiten und dann den neuen Wert natürlich wieder in die Datenbank schreiben. Anschließend müssen die Sperren wieder aufgehoben werden. Ich wollte das etwa so machen:

Code: Alles auswählen

	get_config
server_connect_oe
mysql $myconnoe "LOCK TABLES sortierung WRITE;"
MAXNR=`mysql $myconnoe "SELECT MAX(Nummer) FROM sortierung;"`
MAXNR=$((MAXNR+1))
mysql $myconnoe "INSERT INTO sortierung (Nummer) VALUES ($MAXNR);"
mysql $myconnoe "UNLOCK TABLES;":

Das funktioniert aber leider nicht da die mysql-Verbindung nach dem Ausführen des Befehls geschlossen wird und für den nächsten Befehl eine neue Verbindung aufgebaut wird. Jetzt meine Frage, bekomme ich das relativ einfach in Python hin das ich einmal eine Verbindung aufbaue und diese dann immer wieder nutzen kann solange das Script läuft?
Kann ich ein Python-Script aus der Bash heraus aufrufen und diesem eine oder mehrere Optionen mitgeben? Wie bekomme ich das Ergebnis dann zurück in das Bash-Script bzw. in den kommander?
Und eine letzte Frage (erstmal :wink: ) wie kann ich meine Config-Dateien weiter nutzen? Die sind im Moment im etc-Verzeichnis und so aufgebaut

Code: Alles auswählen

variable1="Wert1"
variable2="Wert2"
...
In der Bash source ich einfach die Datei und habe dann die Werte in den Variablen mit denen ich z.B. eine Verbindung zur Datenbank aufbauen kann. Alles was ich dazu bisher für Python gesehen habe sah mächtig kompliziert aus.
Ich habe die letzten Tage schon einiges an Dokus gelesen und Foren durchsucht aber leider nicht wirklich brauchbare Antworten auf meine Fragen gefunden. Wenn jemand gute Dokus oder auch Beispiele kennt wäre ich sehr dankbar.


Carsten
murph
User
Beiträge: 622
Registriert: Freitag 14. April 2006, 19:23
Kontaktdaten:

also in python bleibt die verbindung einfach so konstant, da musst du nichts machen.
einmal die klasse aufrufen und den wert in einer variable speichern, und dann von der aus alles machen.

Code: Alles auswählen

class A:
    def a(self):
        self.b = 2
        returner = self.b
        self.b+=2
        return returner
klassenaufruf = A()
print klassenaufruf.a
print klassenaufruf.a
klassenaufruf2 = A()
print klassenaufruf2.a
print klassenaufruf2.a

Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

carsten hat geschrieben:ich habe schon öfter von Python gehört und auch schon ein paar mal drüber nachgedacht, mich damit zu beschäftigen.
Hallo Carsten!

Willkommen hier im Forum.
Du wirst es sicher nicht bereuen, dass du dich jetzt mit Python befasst. 8)

carsten hat geschrieben:bekomme ich das relativ einfach in Python hin das ich einmal eine Verbindung aufbaue und diese dann immer wieder nutzen kann solange das Script läuft?
Ja, du kannst zuerst deine Verbindung aufbauen, mehrere SQL-Anfragen an die MySQL-Datenbank schicken, die Rückgaben der Anfragen bearbeiten, zurückspeichern und ganz zum Schluss schließt du die Verbindung wieder. Ja -- das ist kein Problem.

carsten hat geschrieben:Kann ich ein Python-Script aus der Bash heraus aufrufen und diesem eine oder mehrere Optionen mitgeben?
Ja! Das Python-Modul "optparse" ermöglicht es dir, Kommandozeilenparameter auszuwerten. Die Kommandozeilenparameter sind mit dem Befehl sys.argv abrufbar.

carsten hat geschrieben:Wie bekomme ich das Ergebnis dann zurück in das Bash-Script bzw. in den kommander?
Du kannst ganz normal mit dem Befehl "print" etwas in die Konsole schreiben. Alles was direkt in die Konsole geschrieben wird, kannst du mit | oder > in der Bash weiterleiten und weiterverwenden.
Es gibt sogar eine Trennung zwischen STDOUT und STDERR. Du kannst auch Daten über die STDIN, also über die Pipe an das Python-Programm übergeben.

carsten hat geschrieben:wie kann ich meine Config-Dateien weiter nutzen? Die sind im Moment im etc-Verzeichnis und so aufgebaut

Code: Alles auswählen

variable1="Wert1"
variable2="Wert2"
...
Das ist auch kein Problem. Python kann Textdateien lesen und zeilenweise durchlaufen. Das könnte in etwa so aussehen:

Code: Alles auswählen

f = file("config.conf", "rU")
for line in f:
    name, wert = line.split("=")
    name = name.strip()
    wert = wert.strip().strip('"')
#...
f.close()
file = Öffnet eine Datei
split("=") = Trennt einen String bei jedem Vorkommen von "="
strip() = Entfernt Leerzeichen und Zeilenumbrüche am Anfang und am Ende
strip('"') = Entfernt doppelte Anführungszeichen am Anfang und am Ende

Wie du siehst, ist Python sehr flexibel. ;-)

mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
carsten
User
Beiträge: 2
Registriert: Mittwoch 21. Juni 2006, 18:13

Hallo,
vielen Dank erstmal für die Antworten. Leider habe ich wirklich keine Ahnung von Objektorientierter Programmierung und deshalb stelle ich mich vielleicht etwas blöd an.
Ich habe mir bisher Bash-Scripte ohne "Hauptteil" also nur mit Funktionen geschrieben. Aufgerufen habe ich die dann mit "Scriptname Funktion Option1 Option2 ...". Wenn jemand das Script einfach so aufgerufen hat ist also gar nichts passiert. Mit z.B. "meinscript hole_kundendaten 1123" ist in "meinscript" die Funktion "hole_kundendaten" aufgerufen worden. In "hole_kundendaten" wurde dann die Config gelesen und mit diesen Daten wurde eine Verbindung zum Datenbankserver hergestellt. Anschließend wurden die Kundendaten für den Kunden 1123 (steht in $1) geholt und zurückgegeben.
Jetzt möchte ich das in python machen. Nachdem was ich bisher gelesen habe kann ich dort eine Funktion main einrichten, muss es aber nicht. Dort könnte ich dann prüfen ob das Script schon läuft oder gerade erst gestartet wurde. Mmmh wie? Beim ersten Start ein PID-File schreiben und das beim Beenden wieder löschen?
In diese main-Funktion könnte dann auch das Einlesen der Config und der Verbindungsaufbau zum Datenbankserver rein.
Aber wie mache ich das mit meiner Config? Dort stehen derzeit Wahllos Variablen und Kommentare drin. Die Zeile

Code: Alles auswählen

dbserver="my.at.home"
kann in der ersten Zeile, in der fünften oder in der neunten stehen. Im Bash-Script schreibe ich dann einfach

Code: Alles auswählen

myconn="-h "$dbserver"...
und bekomme eine Verbindung zu "my.at.home".
Und wie baue ich die ganze Geschichte mit Python am besten auf? Mit Funktionen? Oder mit Klassen? Wie greife ich dann auf die Datenbank zu?
Theorie: Ich habe eine Funktion "erstelle_db_verbindung". Diese holt zuerst die Werte aus der Config und baut dann eine Verbindung zur DB auf.

Code: Alles auswählen

 import MySQLdb
conn = MySQLdb.connect (host = "localhost",
user = "testuser",
passwd = "testpass",
db = "test")
Wie bekomme ich jetzt z.B. den Inhalt von $dbserver an die Stelle wo jetzt localhost steht?


Carsten
murph
User
Beiträge: 622
Registriert: Freitag 14. April 2006, 19:23
Kontaktdaten:

also je nach sinnzusammenhang funktionen oder klassen,
variablen sind in solchen fällen am besten mit %-Zeichen zu setzen.

Code: Alles auswählen

 
import MySQLdb
host = "localhost"
user = "testuser"
passwort = "testpass"
db = "test")
conn = MySQLdb.connect (host,user,passwort,db)
argumente übernimmst du am besten mit sachen wie optparse, getopt oder sys.
ich bervorzuge sys.argv, wobei dann sys.argv[1] das erste argument ist (als trennung werden leerschritte genommen)
sys.argv[2] logischerweise das zweite.
und wie du auf die datennak zugreifst?
das steht bei google und  im forum (SUFU!!!)
Benutzeravatar
STiGMaTa_ch
User
Beiträge: 32
Registriert: Sonntag 14. Mai 2006, 22:58
Wohnort: Rueti ZH, Schweiz

carsten hat geschrieben:Leider habe ich wirklich keine Ahnung von Objektorientierter Programmierung [...] Ich habe mir bisher Bash-Scripte ohne "Hauptteil" also nur mit Funktionen geschrieben.

Aufgerufen habe ich die dann mit "Scriptname Funktion Option1 Option2 ...".
Du schienst nicht nur von OOP keine Ahnung zu haben, sondern auch von prozeduraler Programmierung ;-)

Um eine Bash Funktion aufzurufen musst du diese entweder in dem File machen, in welchem du die Funktion definiert hast oder aber du erstellst ein zweites Script welches das File mit den darin enthaltenen Funktionen sourced und dann die entsprechende Funktion aufruft.

Um "Skriptname Funktion Option[n]" verwenden zu können musst du die übergabewerte "$1 $2 etc" parsen und entsprechend danach handeln. Denn "Funktion" ist in dem Fall nichts weiter als eine Option!

Wenn du solch Grundlegende Dinge nicht verstehst, wirst du auch an Python keine Freude haben... (Zumindest was die Problemlösung anbelangt ;-) )

Lieber Gruss
STiGMaTa
EDV-Systeme verarbeiten, womit sie gefüttert werden. Kommt Mist rein, kommt Mist raus. (André Kostolany)
BlackJack

Da ich im Moment keine Datenbank laufen habe, ist die entsprechende Funktion ungetestet. Aber ungefähr so geht's:

Code: Alles auswählen

import sys
from ConfigParser import ConfigParser
import MySQLdb


def test_cmd(config, args):
    connection = MySQLdb.connect(host=config.get('db', 'dbserver'),
                                 user=config.get('db', 'db_user'),
                                 passwd=args[0])
    cursor = connection.cursor()
    cursor.execute('LOCK TABLES sortierung WRITE')
    cursor.execute('SELECT MAX(Nummer) FROM sortierung')
    max_nr = cursor.fetchone()[0]
    cursor.execute('INSERT INTO sortierung (Nummer) VALUES (%s)', (max_nr + 1,))
    cursor.execute('UNLOCK TABLES')
    connection.commit()
    connection.close()


def dump_cmd(config, args):
    for section in config.sections():
        print 'Section %s:' % section
        for item in config.items(section):
            print '  %s -> %s' % item
    print 'Arguments: %r' % args


def main():
    config = ConfigParser()
    config.read('test.conf')

    commands = { 'test': test_cmd,
                 'dump': dump_cmd }
    
    try:
        command = commands[sys.argv[1]]
    except KeyError:
        sys.exit('unknown command %r' % sys.argv[1])
    command(config, sys.argv[2:])


if __name__ == '__main__':
    main()
Für die Konfigurationsdatei wird `ConfigParser` benutzt und die `test.conf` sieht so aus:

Code: Alles auswählen

# Section Header ist (leider?) Pflicht

[db]
dbserver=my.at.home
db=test
db_user=me
Kommentare kann man wie bei der Bash mit einem ``#`` kennzeichnen. `ConfigParser` verlangt zwingend "Sections" also habe ich hier eine (``[db]``) hinzugefügt.

Die Funktion `test_cmd()` zeigt wie man mit Datenbanken umgeht. Ist wie gesagt ungetestet.

Die `dump_cmd()` gibt die Konfigurationsdaten und die Argumente einfach nur aus. Die Funktion gibt's hauptsächlich damit zwei Funktionen da sind, zwischen denen man wählen kann.

In der `main()` ist eine Möglichkeit aufgezeigt je nach Inhalt des ersten Arguments auf der Kommandozeile eine Funktion aufzurufen, der die Konfiguration und die restlichen Argumente übergeben werden. Beispielaufrufe:

Code: Alles auswählen

$ ./test.py dump a b c
Section db:
  db_user -> me
  db -> test
  dbserver -> my.at.home
Arguments: ['a', 'b', 'c']

$ ./test.py fiep
unknown command 'fiep'
Antworten