2016-08-04 4 views
0

こんにちは、私は "リストの範囲外の"エラーが私のsqlite3データベースにデータを挿入しようとしている間にいくつかのヘルプを探しています。Python:sqlite3:リストのインデックスが範囲外にある

これは、クラスヘルパーを使用してデータベースとの間でデータを解析する最初の試みです。そのため、扱いにくいコーディングを笑わないでください。 :))

ここに私のクラスをテストするための私のmain.pyです。

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

これは、データベースを作成し、テーブルエントリを作成します。 ここに、私のDatabaseHelperクラスの私のinsertIntoメソッドがあります。

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

「リストのインデックスが範囲外です」というエラーをスローします。

ご協力いただきありがとうございます。

+0

'文字列.__ lenは__()は'良くLEN 'のように書かれています(文字列) 'です。 – Ryan

+0

ええ、Ryanに感謝します。プログラミングの初心者であり、多くの方法であなたのことを頼りにしています。毎日は学校の日です。 :) – Forbidden303

答えて

2

あまりにも多くの文字列操作がそこに続いています。このinsertIntoはあなたが望むものにおそらく近い:

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

は、ここで重要な変更点は次のとおりです。

  • str.join項目のすべてをINGの代わりの次の部分と、ループ内の区切り文字を連結し、後で区切り文字を切り取ります。

    >>> ', '.join(['one', 'two', 'three']) 
    'one, two, three' 
    
  • を部品に名前を付ける代わりに+オペレータ束を使用して文字列を構築するためにstring formattingの使用:ここで

    は、それがどのように動作するかです。読むのが簡単です。

  • リスト乗算を使用して、いくつかの数の?プレースホルダを取得します。

    >>> ['?'] * 5 
    ['?', '?', '?', '?', '?'] 
    
  • dataを渡す代わりに、テキスト'(data[0], data[1], …)'の文字列のパラメータとして:ここ

    とは、それがどのように動作するかです。 dataは、おそらくあまりにも、タプルでなければなりません:

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

私もDatabaseHelperを表すことになっているかわからないんだけど。それに関連する州はありますか? self.db_nameself.table_nameself.column_dataself.data ...それらはすべてすべての挿入で上書きされるようです。データベース接続は、しかし、データベースのヘルパーに関連付ける便利な状態のように思える:

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) 

その後、あなたはこのようにそれを使用することができます:

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

おかげさまでライアンは、あなたが投稿したものを見て、どんな成功を収めて戻ってきます。何が起こっているのかを勉強するのに少し時間がかかるかもしれませんが、助けてくれてありがとう。 – Forbidden303

+0

++、@ Forbidden303ここで重要な変更は、あなたが何をしていてもクエリーにパラメータを使用することです。データベースコマンドとして解釈される 'data'のテキストと[巨大なエクスプロイトホール] (http://security.stackexchange.com/questions/128412/sql-injection-is-17-years-old-why-is-it-still-around/) – TessellatingHeckler

+0

@Ryanまあ私は私の帽子を取る必要がありますあなたへ。このバージョンは修正なしで初めて動作しました。 .format()メソッドを中括弧で展開すると、実際にはよりクリーンになります。また、結合メソッドとリストの乗算は、はるかに元気な方法です。宣言しているself.varsに関しては、オブジェクトがある期間、「生きている」状態であり、私がvarsを参照する必要がある場合にのみ、これが必要であると思いますか?とにかく男、時間を割いてくれてありがとう、それは確かに教育だった。とても感謝しております。 – Forbidden303

関連する問題