XML Datei in Datenbank schreiben .. Fehler

Installation und Anwendung von Datenbankschnittstellen wie SQLite, PostgreSQL, MariaDB/MySQL, der DB-API 2.0 und sonstigen Datenbanksystemen.
Antworten
pfff
User
Beiträge: 7
Registriert: Mittwoch 13. Juli 2011, 11:41

Hi,

ich möchte mit einem Script eine XML Datei auslesen und dann einige Daten daraus auf eine Datenbank schreiben.

Die Daten konnte ich schon herausfiltern nur mit dem Zugriff auf die Serverdatenbank gibt es ein Problem das ich nicht finde...ich programmiere leider erst seit 2 Tagen und hab darum nicht den Durchblick überall :P

vllt könnt ihr mir helfen?


Normal stehn bei User und PW natürlich meine Daten..

Code: Alles auswählen


import xml.dom.minidom as dom
import glob
import sys
import MySQLdb

connection = MySQLdb.connect(host="192.168.249.20", user="*****", passwd="*****", db="ov_new_movies")
cursor = connection.cursor()

print "---------"
print "XML-Files"
print "---------"

path = sys.argv[1] + sys.argv[2] + '.xml'


for file in glob.glob(path):
    print '\n' +  file

    baum = dom.parse(file)

    for eintrag in baum.firstChild.childNodes:
        if eintrag.nodeName == "release":
            mrelease = eintrag.nodeName
            print "Release: " + eintrag.firstChild.data.strip()
       
        if eintrag.nodeName == "year":
            myear = eintrag.nodeName
            print "Year: " + eintrag.firstChild.data.strip()
       
        if eintrag.nodeName == "duration":
            mduration = eintrag.nodeName
            print "Duration: " + eintrag.firstChild.data.strip()
    	
        if eintrag.nodeName == "languages":
            for knoten in eintrag.childNodes:
                if knoten.nodeName == "language":
                    mlanguage = knoten.nodeName
                    print "language: " + knoten.getAttribute("name")
                    for knoten in knoten.childNodes:
                        if knoten.nodeName == "title":
                            mtitel = knoten.nodeName
                            print "Title: " + knoten.firstChild.data.strip()
                        if knoten.nodeName == "full":
                            mfull = knoten.nodeName
                            print "Full: " + knoten.firstChild.data.strip()
                        if knoten.nodeName == "credits":
                            for knoten in knoten.childNodes:
                                if knoten.nodeName == "item":
                                    mitem = knoten.nodeName
                                    print "Credits: " + knoten.firstChild.data.strip()
                                    pass
                                pass
                            pass
                        pass
                    pass
                pass
            pass       						
        if eintrag.nodeName == "assets":            				
            for knoten in eintrag.childNodes:
                if knoten.nodeName == "asset":
                    mname = knoten.nodeName
                    print "Name: " + knoten.getAttribute("name")
                    pass
                    
    daten = ((mtitel, mrelease, myear, mduration, mlanguage, mfull, mitem, mname))
    cursor.executemany("INSERT INTO ov_new_movies VALUES(%s, %s, %s, %s, %s, %s, %s, %s)", daten)

Folgender Fehler kommt dann zu stande:

Code: Alles auswählen

pfruehwirth@NBJB:~/workspace/Test$ python Test /private/var/cache/cds/cds_inbox/ takingwoods
Traceback (most recent call last):
  File "Test", line 6, in <module>
    connection = MySQLdb.connect(host="192.168.249.20", user="root", passwd="Bhu89ol.", db="ov_new_movies")
  File "/usr/local/lib/python2.6/dist-packages/MySQL_python-1.2.3-py2.6-linux-i686.egg/MySQLdb/__init__.py", line 81, in Connect
    return Connection(*args, **kwargs)
  File "/usr/local/lib/python2.6/dist-packages/MySQL_python-1.2.3-py2.6-linux-i686.egg/MySQLdb/connections.py", line 187, in __init__
    super(Connection, self).__init__(*args, **kwargs2)
_mysql_exceptions.OperationalError: (1049, "Unknown database 'ov_new_movies'")
Zuletzt geändert von Anonymous am Mittwoch 13. Juli 2011, 12:54, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Code-Tags gesetzt.
frabron
User
Beiträge: 306
Registriert: Dienstag 31. März 2009, 14:36

Ich heb's dir mal hervor, du musst nur noch übersetzen ;)

Code: Alles auswählen

_mysql_exceptions.OperationalError: (1049, "Unknown database 'ov_new_movies'")
pfff
User
Beiträge: 7
Registriert: Mittwoch 13. Juli 2011, 11:41

das hab ich schon entdeckt :P

nur die Datenbank hab ich auf dem Server angelegt ;(
frabron
User
Beiträge: 306
Registriert: Dienstag 31. März 2009, 14:36

Nun, offensichtlich kracht es ja schon hier

Code: Alles auswählen

connection = MySQLdb.connect(host="192.168.249.20", user="*****", passwd="*****", db="ov_new_movies")
Also heisst entweder die Datenbank nicht so, der Server hat eine andere IP oder du benutzt einen anderen Port als den Standardport. Eine Firewall ist auch immer ein beliebtes Problem bei der Kommunikation über Rechner hinweg ...
pfff
User
Beiträge: 7
Registriert: Mittwoch 13. Juli 2011, 11:41

also IP, und DB name stimmt ;( ich seh mal wegen Firewall thx
pfff
User
Beiträge: 7
Registriert: Mittwoch 13. Juli 2011, 11:41

Zugriff auf die DB hab ich nun .. war ein fehlerhafter Name stimmt :?

Code: Alles auswählen

  File "Test", line 65, in <module>
    cursor.executemany("INSERT INTO ov_new_movies VALUES(%s, %s, %s, %s, %s, %s, %s, %s)", daten)
  File "/usr/local/lib/python2.6/dist-packages/MySQL_python-1.2.3-py2.6-linux-i686.egg/MySQLdb/cursors.py", line 206, in executemany
    r = r + self.execute(query, a)
  File "/usr/local/lib/python2.6/dist-packages/MySQL_python-1.2.3-py2.6-linux-i686.egg/MySQLdb/cursors.py", line 159, in execute
    query = query % db.literal(args)
TypeError: not enough arguments for format string

ich übergeb hier ja Texte und Zahlen...laut der Seite wo ich das nachgesehen habe kann ich dafür immer %s schreiben da das Mysqldb modul sich die einzelnen Elemente selbst formatiert..

muss ich das nun doch ändern um den Fehler oben zu beseitigen?
frabron
User
Beiträge: 306
Registriert: Dienstag 31. März 2009, 14:36

TypeError: not enough arguments for format string
Meint, du hast zu viele "%s" in
cursor.executemany("INSERT INTO ov_new_movies VALUES(%s, %s, %s, %s, %s, %s, %s, %s)", daten)
oder zu wenig Werte in Daten, je nach dem ...
BlackJack

@pfff: Du verwendest die falsche Methode. `executemany()` will nicht die Daten für *einen* Datensatz haben, sondern für mehrere. Du übergibst aber nur ein Tupel mit Einzelwerten. Falls Du dachtest Du hast da ein Tupel in einem Tupel: Klammern erzeugen kein Tupel (bis auf den Sonderfall des leeren Tupels) sondern sind einfach nur Klammern. Tupel mit Elementen werden durch Kommata erzeugt. Aber Du willst hier wahrscheinlich einfach nur `execute()` mit *einem* Datensatz verwenden.
pfff
User
Beiträge: 7
Registriert: Mittwoch 13. Juli 2011, 11:41

@pfff: Du verwendest die falsche Methode. `executemany()` will nicht die Daten für *einen* Datensatz haben, sondern für mehrere. Du übergibst aber nur ein Tupel mit Einzelwerten. Falls Du dachtest Du hast da ein Tupel in einem Tupel: Klammern erzeugen kein Tupel (bis auf den Sonderfall des leeren Tupels) sondern sind einfach nur Klammern. Tupel mit Elementen werden durch Kommata erzeugt. Aber Du willst hier wahrscheinlich einfach nur `execute()` mit *einem* Datensatz verwenden.
ah vielen dank, nun schreibt er schon mal in die DB ;)
pfff
User
Beiträge: 7
Registriert: Mittwoch 13. Juli 2011, 11:41

Das mit dem übergeben in die Datenbank funktioniert so weit..eine Frage hätt ich aber noch.

mein Element release ließt ein Datum aus der XML Datei im Format 13 Nov 2009 ... ist es möglich das man dieses Format mit einem Befehl ändert in 2009-11-13 um es in der Datenbank als Date verwenden zu können?

oder muss ich es einzeln Splitten und zusammenfügen?
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Schau dir dazu am besten das datetime-Modul an, darin gibt es Funktionen zum parsen von Datumsstrings.
Das Leben ist wie ein Tennisball.
pfff
User
Beiträge: 7
Registriert: Mittwoch 13. Juli 2011, 11:41

ich habs jz mal so gelöst inzwischen..

Code: Alles auswählen

srelease = mrelease.split()
            
            if srelease[1] == "Jan":
                srelease[1] = "01"
            if srelease[1] == "Feb":
                srelease[1] = "02"
            if srelease[1] == "Mar":
                srelease[1] = "03"
            if srelease[1] == "Apr":
                srelease[1] = "04"        
            if srelease[1] == "May":
                srelease[1] = "05"
            if srelease[1] == "Jun":
                srelease[1] = "06"
            if srelease[1] == "Jul":
                srelease[1] = "07"
            if srelease[1] == "Aug":
                srelease[1] = "08"
            if srelease[1] == "Sep":
                srelease[1] = "09"
            if srelease[1] == "Oct":
                srelease[1] = "10"
            if srelease[1] == "Nov":
                srelease[1] = "11"
            if srelease[1] == "Dez":
                srelease[1] = "12"
                    
            mrelease = srelease[2] + '-' + srelease [1] + '-' + srelease[0]
            print "Release: " + mrelease   
aber danke ich werd gleich das Date genauer anschauen
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Hallo.

An deinem Code hast du viele Dinge demonstriert, die man verbessern könnte ;-) Als wichtigster Punkt natürlich, dass Funktionen aus der Standardbibliothek den selbstgeschriebenen vorzuziehen sind, da sie im Normalfall besser getestet, allgemeiner und zudem zeitsparend sind. Dann fällt bei deinem Code natürlich sofort auf, dass du unzählige Wiederholungen hast. Statt jedes Mal `srelease[1]` zu verwenden, kannst du das auch an einen Namen binden. Weiter sollte dir auffallen, dass es sich um eine einfache Abbildung von Monatsnamen auf Zahlen handelt. Zu diesem Zweck bietet sich ein Dictionary gerade zu an. Das kann man sogar erzeugen lassen, ohne dass man alle Zahlen hinschreiben muss. Außerdem solltest du die Zahlen nicht als Strings speichern, sondern besser später umwandeln. Die Nummer eines Monats ist nunmal kein String sondern eine Zahl.

Außerdem solltest du dir noch einmal `elif` anschauen und die Suchmaschine deiner Wahl nach "String Formatting" befragen. Strings sollten nämlich nicht mit `+` zusammengesetzt werden, sondern über die dafür vorgesehenen Mechanismen. So kann man bei einstelligen Zahlen zum Beispiel automatisch Nullen voranstellen lassen ;-) Das Zusammensetzen beim `print`-Aufruf ist ebenfalls überflüssig, ein einfaches Komma hätte es hier auch getan.

Mit den genannten Tipps solltest du dein Programm hoffentlich ein ganzes Stück verbessern und verkürzen können.

Sebastian
Das Leben ist wie ein Tennisball.
Antworten