简体   繁体   中英

Python: sqlite3: List index out of range

Hi i am looking for some help with an "List index out of range" error i am getting while trying to insert data into my sqlite3 database.

This is my first attempt at using a class helper to parse data to and from my database, so please don't laugh at my unwieldy coding. :))

here is my main.py for testing out my class.

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()

Which creates the database and creates the table entries. Here is my insertInto method from my DatabaseHelper class.

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()

Which throws an "List index out of range" error.

Any help would be much appreciated, thanks.

There is way too much string manipulation going on there. This insertInto is probably closer to what you want:

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()

The key changes here are:

  • str.join ing all of the items instead of concatenating the next part and a delimiter in a loop, then slicing away the delimiter afterwards.

    Here's how it works:

     >>> ', '.join(['one', 'two', 'three']) 'one, two, three' 
  • Using string formatting to build strings by naming parts instead of using the + operator a bunch. It's easier to read.

  • Using list multiplication to get some number of ? placeholders.

    And here's how that works:

     >>> ['?'] * 5 ['?', '?', '?', '?', '?'] 
  • Passing data as a parameter instead of a string with the text '(data[0], data[1], …)' . data should probably be a tuple, too:

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

I'm also not sure what a DatabaseHelper is supposed to represent. Does it have any state associated with it? self.db_name , self.table_name , self.column_data , self.data … they all seem to get overwritten with every insertion. A database connection seems like useful state to associate with a database helper, though:

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)

Then you can use it like this:

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()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM