2016-08-04 32 views
0

Hallo, ich bin auf der Suche nach Hilfe mit einem "Listenindex außerhalb des Bereichs" -Fehlers, den ich erhalte, während ich versuche, Daten in meine sqlite3-Datenbank einzufügen.Python: sqlite3: Listenindex außerhalb des Bereichs

Dies ist mein erster Versuch, einen Klassenhelfer zu verwenden, um Daten zu und von meiner Datenbank zu analysieren, also lache bitte nicht über meine unhandliche Kodierung. :))

hier ist mein main.py zum Testen meiner Klasse.

import kivy 
kivy.require('1.9.1') 

from databaseHelper import DatabaseHelper 
from kivy.app import App 
from kivy.uix.widget import Widget 


class Window1(Widget): 
    pass 

class MyApp(App): 
    def build(self): 

     db = DatabaseHelper() 
     db.createDatabase('myDatabase') 
     columnData = ['unix', 'value', 'datestamp', 'keyword'] 
     data = [57489543789, 2096, "12-12-12", "hello data"] 

     db.createTable(db.name, "datatable", columnData) 
     db.insertInto(db.name, "datatable", columnData, data) 
     return Window1() 


if __name__ == '__main__': 
    MyApp().run() 

Erstellt die Datenbank und erstellt die Tabelleneinträge. Hier ist meine insertInto-Methode aus meiner DatabaseHelper-Klasse.

def insertInto(self, db_name, table_name, column_data, data): 
     self.db_name = db_name 
     self.table_name = table_name 
     self.column_data = column_data 
     self.data = data 

    try: 
     conn = sqlite3.connect(self.db_name) 
     c = conn.cursor() 

     dataString = '' 
     string = '' 
     values = '' 
     for i in data: 
      string += column_data[i] + ", " 
      values += '?, ' 
      dataString += 'self.data' + '[' + str(i) + ']' + ', ' 


     string = string[0:string.__len__() - 2] 
     values = values[0:values.__len__() - 2] 
     dataString = dataString[0:dataString.__len__() - 2] 

     c.execute("INSERT INTO " + self.table_name + " (" + string + ")" + " VALUES " + "(" + values + ")", 
       "(" + dataString + ")"             
       ) 
     conn.commit() 
     print("Succesfully input data into database: " + self.db_name + " Table: " + self.table_name) 

    except Exception as e: 
     print("Failed to input data into database: " + self.db_name + " Table: " + self.table_name) 
     print(e) 

    finally: 
     c.close() 
     conn.close() 

, die eine "List Index out of range" Fehler auslöst.

Jede Hilfe wäre sehr geschätzt, danke.

+0

'String .__ len __()' besser geschrieben als 'len (Zeichenfolge) '. – Ryan

+0

Ja, danke Ryan. Irgendwie neu in der Programmierung und ich vertraue auf YouCompleteme für viele Methoden.Jeder Tag ist ein Schultag. :) – Forbidden303

Antwort

2

Es gibt viel zu viel String-Manipulation dort. Diese insertInto ist wahrscheinlich näher an, was Sie wollen:

def insertInto(self, db_name, table_name, column_data, data): 
    self.db_name = db_name 
    self.table_name = table_name 
    self.column_data = column_data 
    self.data = data 

    try: 
     conn = sqlite3.connect(self.db_name) 
     c = conn.cursor() 

     c.execute(
      "INSERT INTO {table} ({columns}) VALUES ({parameters})".format(
       table=table_name, 
       columns=', '.join(column_data), 
       parameters=', '.join(['?'] * len(column_data)), 
      ), 
      data 
     ) 
     conn.commit() 

     print("Succesfully input data into database: " + self.db_name + " Table: " + self.table_name) 
    except Exception as e: 
     print("Failed to input data into database: " + self.db_name + " Table: " + self.table_name) 
     print(e) 
    finally: 
     c.close() 
     conn.close() 

Die wichtigsten Änderungen sind hier:

  • str.join alle Elemente ing statt den nächsten Teil und ein Trennzeichen in einer Schleife verketten, dann Entfernen Sie anschließend das Trennzeichen.

    Hier ist, wie es funktioniert:

    >>> ', '.join(['one', 'two', 'three']) 
    'one, two, three' 
    
  • string formatting mit Hilfe von Strings aufzubauen, indem Teile anstelle der Verwendung des + Operator ein paar zu nennen. Es ist einfacher zu lesen.

  • Verwenden der Listenmultiplikation, um eine Anzahl von ? Platzhaltern zu erhalten.

    Und hier ist, wie das funktioniert:

    >>> ['?'] * 5 
    ['?', '?', '?', '?', '?'] 
    
  • Passing data als Parameter anstelle einer Zeichenfolge mit dem Text '(data[0], data[1], …)'. data sollte wohl ein Tupel sein, auch:

    columnData = ('unix', 'value', 'datestamp', 'keyword') 
    data = (57489543789, 2096, "12-12-12", "hello data") 
    

Ich bin auch nicht sicher, was ein DatabaseHelper darstellen soll. Hat es irgendeinen Staat damit verbunden? self.db_name, self.table_name, self.column_data, self.data ... sie scheinen bei jedem Einfügen überschrieben zu werden. obwohl eine Datenbankverbindung scheint, wie nützlich Zustand mit einer Datenbank Helfer zu assoziieren,:

class DatabaseHelper: 
    def __init__(self, db_name): 
     self.connection = sqlite3.connect(self.db_name, isolation_level=None) 

    def close(self): 
     self.connection.close() 

    def insertInto(self, table_name, columns, data): 
     query = "INSERT INTO {table} ({columns}) VALUES ({parameters})".format(
      table=table_name, 
      columns=', '.join(columns), 
      parameters=', '.join(['?'] * len(columns)) 
     ) 

     self.connection.execute(query, data) 

     print("Succesfully input data into database: " + db_name + " Table: " + table_name) 

Dann können Sie diese verwenden Sie es wie:

class MyApp(App): 
    def build(self): 
     db = DatabaseHelper('myDatabase') 
     columnData = ('unix', 'value', 'datestamp', 'keyword') 
     data = (57489543789, 2096, "12-12-12", "hello data") 

     db.createTable("datatable", columnData) 
     db.insertInto("datatable", columnData, data) 
     return Window1() 
+0

Danke, Ryan, werde einen Blick darauf werfen, was du gepostet hast und mit jedem Erfolg zurückkommen. Kann ein wenig Zeit brauchen, um zu studieren, was vor sich geht, aber danke, dass du geholfen hast. – Forbidden303

+0

++, @ Forbidden303 eine große Änderung hier, die Sie einschließen sollten, was auch immer Sie tun, ist die Verwendung der Parameter in der Abfrage, es wird verhindern, dass der Text in 'Daten' als Datenbankbefehle interpretiert wird und ein [großes Exploitloch] (http://security.stackexchange.com/questions/128412/sql-injection-is17-years-old-why-is-it-still-around/) – TessellatingHeckler

+0

@Ryan Nun, Sir, ich muss meinen Hut ablegen für dich. Diese Version funktionierte zum ersten Mal ohne Änderungen. Die Verwendung der .format() -Methode mit geschweiften Klammern Erweiterung ist wirklich viel sauberer und die Join-Methoden und Listen-Multiplikation sind eine viel vernünftigere Art, Dinge zu tun. Was die Deklaration von self.vars betrifft, so ist dies nur erforderlich, wenn das Objekt für eine bestimmte Zeit 'am Leben' bleibt und ich mich auf vars beziehen muss? Wie auch immer, Danke, dass du dir die Zeit genommen hast zu helfen, es war sicherlich eine Ausbildung. Herzlichen Dank. – Forbidden303