2

いくつかのデータをsqlite3に保存するPythonプログラムがあり、それを別のOSで使用したいと思いました。

Windows 7ではプログラムは正常に動作しますが、Ubuntu12.04では動作しません。

問題は次のとおりです。空のタプルをsqliteデータベースに(からの文字列として " ".join( ... ))格納し、それをWindowsに読み戻すと、空のタプルが取得されますが()、Ubuntuでは取得されNoneます。

私のテストコードは次のとおりです。

import sqlite3
import os

def adapt_tuple(tpl):
    return " ".join(str(n) for n in tpl)

def get_tuple(s):
    return tuple([int(x) for x in s.split()])

emptytuple=()
goodtuple=(1,2)

sqlite3.register_adapter(tuple,adapt_tuple)
sqlite3.register_converter("tuple_of_ints",get_tuple)

myconn=sqlite3.connect('test.db',detect_types=sqlite3.PARSE_DECLTYPES)
myconn.execute("""CREATE TABLE test(number int, tuple tuple_of_ints);""")

goodentry=(1,goodtuple)
emptyentry=(2,emptytuple)

myconn.execute("""INSERT INTO test VALUES (?,?);""", goodentry)
myconn.execute("""INSERT INTO test VALUES (?,?);""", emptyentry)

for row in myconn.execute("""SELECT * FROM test;"""):
    print row

myconn.close()
os.remove('test.db')

これにより、次の出力が得られます。

(1, (1, 2))
(2, ())

Windowsと:

(1, (1, 2))
(2, None)

Ubuntuで。

私はそれをチェックしました

get_tuple(adapt_tuple(emptytuple))

両方のシステムで同じ出力が得られる()ため、sqlite3を実行することと関係がある必要があります。

sys.version_infoPythonでの出力は両方のシステムで同じであるsqlite3.versionため、オペレーティングシステムと関係があると確信しています。

だからsumarryで、私の質問は:なぜこれが起こっているのですか?そして、Ubuntuバージョンが最後に空のタプルを返すようにするにはどうすればよいですか?

返信ありがとうございます。アップル。

ノート

最初に言及したはずですが、adapt_tuple出力を印刷する" "と、両方のオペレーティングシステムで取得できます。

4

2 に答える 2

1

WindowsとUbuntuの不一致については説明できませんが、Ubuntuの回避策は次のとおりです。

def adapt_tuple(tpl):
    return " ".join(str(n) for n in tpl) or ' '
于 2013-02-24T19:13:29.690 に答える
1

あなたのsqliteバージョンの1つがアダプタの戻り値の空の文字列をNULLとして扱っているようです。おそらくsqlite、異なる動作を説明できる異なるバージョンがあります。

その場合は、空の文字列を返さないようにアダプタを変更する必要があります。次に、新しいフォーマットを処理するようにコンバーターを調整する必要もあります。その例を次に示します。

def adapt_tuple(tpl):
    return repr(tpl)

def get_tuple(s):
    if len(s) > 2:
        return tuple(int(x) for x in s[1:-1].split(','))
    return ()

実際の問題はに関連してregister_converterおり、に依存していsqlite3_column_blobます。後者は、長さがゼロのBLOBに対してNULLを返します(sqliteのドキュメントを参照)。次に、pysqliteのコードに次の形式のチェックがあります。

if (!sqlite3_column_blob(...)) converted_col = Py_None;

結果として、コンバーターが空の文字列に対して呼び出されることはなく、Noneが返されます。

問題は、バージョン間で変更される可能性pysqliteのあるの動作に依存することです。実際、それは事実です。sqlite 3.7.3以降、ドキュメントに準拠するように変更されました。それ以前は、空のBLOBでNULLを返しませんでした。したがって、一貫性を保つために、アダプタが空の文字列を返さないようにしてください。sqlite3_column_blobsqlitesqlite3_column_blob

于 2013-02-24T19:13:58.173 に答える