SQLite3(2)

Raspberry Piと直接的には関係無い話だが、前回SQLite3モジュールを使って簡単なデータベースプログラムを作ったときに躓いた箇所があったので、記しておく。

最初に作ったプログラムはデータベースを開いてテーブル作成する部分が、次のようになっていた。

class Measure(threading.Thread):
    def __init__(self, dbname):
        threading.Thread.__init__(self)
        self.con = sqlite3.connect(dbname,
                            isolation_level = None,
                            timeout = 5000)
        self.daemon = True
    def run(self):
        try:
            sql = "create table data(date text primary key, real temp);"
            self.con.execute(sql)
        except Exception, ex:
            print ex

拡張する事を考えてデータベース操作はスレッドに分離して、スレッド初期化の時にデータベースへのコネクションも作成するようにしてあったのだが、実行すると以下のようなエラーが出てしまう。

SQLite objects created in a thread can only be used in that same thread.The object was created in thread id -1225788912 and this is thread id –1231440784

SQLiteのオブジェクトは作成したスレッド内でしか使えない、というエラーだ。調べてみると確かにSQLiteのコネクションはスレッド間で共有できないと書かれていた。

確認のためプログラムのメイン、スレッドの初期化、スレッドのRUNメソッドのそれぞれで、スレッドの識別IDを表示するようにしてみた。

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import smbus
import time
import datetime
import threading
import sqlite3

class Measure(threading.Thread):
    def __init__(self, dbname):
        threading.Thread.__init__(self)
        self.con = sqlite3.connect(dbname,
                            isolation_level = None,
                            timeout = 5000)
        self.daemon = True
        print "init:",threading.currentThread().ident
    def run(self):
        print "run: ",threading.currentThread().ident
        try:
            sql = "create table data(date text primary key, real temp);"
            self.con.execute(sql)
        except Exception, ex:
            print ex

if __name__ == '__main__':
    print "main:",threading.currentThread().ident
    measure = Measure('temperature.db')
    measure.start()
    try:
        while True:
            time.sleep(1)
    except KeyboardInterrupt:
        print '\nbreak'

その結果は以下のようになった。

main: -1225342448
init: -1225342448
run:  -1230994320
SQLite objects created in a thread can only be used in that same thread.The object was created in thread id -1225342448 and this is thread id -1230994320

スレッドの__init__とrunは確かに異なる識別IDになっている。
スレッドの初期化と本体が異なるスレッドなのは当たり前なのだが、普段あまり意識していなかったのでちょっと引っかかってしまった。

複数のスレッドでコネクションを共有できないのは不便な気もするが、同じデータベースに対して複数のコネクションからアクセスするのは大丈夫らしい。同じスレッドの中で作成したコネクションしか使えない、という事だけ注意しておけばRaspberry Piでの使用はそれほど問題にはならないだろう。

広告

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

%s と連携中