web-dev-qa-db-ja.com

SQLite3データベースがPythonに存在するかどうかを確認するにはどうすればよいですか?

SQLiteデータベースを開くために、Python 2.7.3で関数を作成しようとしています。

これは現時点で私のコードです:

_import sqlite3 as lite
import sys

db = r'someDb.sqlite'

def opendb(db):
    try:
        conn = lite.connect(db)
    except sqlite3.Error:
        print "Error open db.\n"
        return False
    cur = conn.cursor()
    return [conn, cur]
_

上記のコードを試しましたが、_sqlite3_ライブラリが宣言されたデータベースが存在する場合はそれを開き、存在しない場合は新しいデータベースを作成することを確認しました。

_sqlite3_メソッドを使用してデータベースが存在するかどうかを確認する方法はありますか、またはos.path.isfile(path)のようなファイル操作を使用する必要がありますか?

19
maxim

Python 2では、 _os.path.isfile_ を使用して、存在を明示的にテストする必要があります。

_if os.path.isfile(db):
_

_sqlite3.connect_関数にファイルを作成させない方法はありません。


Python 3.4以降を使用している場合は、新しいURIパス機能を使用して、データベースを開くときに別のモードを設定できます。デフォルトでsqlite3.connect()関数が開きますrwcのデータベース、つまり読み取り、書き込み、作成モードであるため、存在しないデータベースに接続すると、データベースが作成されます。

URIを使用して、代わりに別のモードを指定できます。 rwに設定すると、Read&Writeモードで、存在しないデータベースに接続しようとすると例外が発生します。接続時に_uri=True_フラグを設定して_file:_ URIを渡し、_mode=rw_クエリパラメータをパスに追加すると、さまざまなモードを設定できます。

_from urllib.request import pathname2url

try:
    dburi = 'file:{}?mode=rw'.format(pathname2url(db))
    conn = lite.connect(dburi, uri=True)
except sqlite3.OperationalError:
    # handle missing database case
_

受け入れられるパラメータの詳細については、 SQLite URIRecognized Query Parametersdocumentation を参照してください。

25
Martijn Pieters

os.path.isfile()は、ファイルが存在し、SQLite3データベースであるかどうかではなく、ファイルが存在するかどうかを通知するだけです! http://www.sqlite.org/fileformat.html を知っているので、これを行うことができます:

def isSQLite3(filename):
    from os.path import isfile, getsize

    if not isfile(filename):
        return False
    if getsize(filename) < 100: # SQLite database file header is 100 bytes
        return False

    with open(filename, 'rb') as fd:
        header = fd.read(100)

    return header[:16] == 'SQLite format 3\x00'

その後、それを次のように使用します:

for file in files:
    if isSQLite3(file):
        print "'%s' is a SQLite3 database file" % file
    else:
        print "'%s' is not a SQLite3 database file" % file
19
Tom Horen

はい、Python 3.4+。

sqlite3.connect()関数を使用して接続しますが、ファイルパスの代わりにURIを渡し、クエリ文字列にmode=rwを追加します。

以下は完全に機能するコード例です。

import sqlite3
con = sqlite3.connect('file:aaa.db?mode=rw', uri=True)

これにより、現在のフォルダーのaaa.dbという名前のファイルから既存のデータベースが開きますが、そのファイルを開けない場合や存在しない場合は、エラーが発生します。

Traceback (most recent call last):
  File "aaa.py", line 2, in <module>
    con = sqlite3.connect('file:aaa.db?mode=rw', uri=True)
sqlite3.OperationalError: unable to open database file

Python sqlite.connect()docs は次のように述べています:

Uriがtrueの場合、データベースはURIとして解釈されます。これにより、オプションを指定できます。たとえば、データベースを読み取り専用モードで開くには、次のコマンドを使用できます。

db = sqlite3.connect( 'file:path/to/database?mode = ro'、uri = True)

認識されるオプションのリストなど、この機能の詳細については、 SQLite URIのドキュメント を参照してください。

http://www.sqlite.org/c3ref/open.html から収集されたすべての関連URIオプション情報の抜粋を次に示します。

mode:モードパラメータは、「ro」、「rw」、「rwc」、または「memory」のいずれかに設定できます。他の値に設定しようとするとエラーになります。 "ro"が指定されている場合、SQLITE_OPEN_READONLYフラグがsqlite3_open_v2()の3番目の引数に設定されている場合と同様に、データベースは読み取り専用アクセス用に開かれます。モードオプションが「rw」に設定されている場合、SQLITE_OPEN_READWRITE(SQLITE_OPEN_CREATEではない)が設定されているかのように、データベースは読み取り/書き込み(作成ではない)アクセス用に開かれます。値「rwc」は、SQLITE_OPEN_READWRITEとSQLITE_OPEN_CREATEの両方を設定することと同等です。モードオプションが「メモリ」に設定されている場合、ディスクからの読み取りや書き込みを行わない純粋なメモリ内データベースが使用されます。 3番目のパラメーターでsqlite3_open_v2()に渡されたフラグで指定された値より制限が少ないモードパラメーターの値を指定すると、エラーになります。

sqlite3_open_v2()インターフェースはsqlite3_open()と同様に機能しますが、新しいデータベース接続をさらに制御するために2つの追加パラメーターを受け入れる点が異なります。 sqlite3_open_v2()へのフラグパラメータは、次の3つの値のいずれかを取り、オプションでSQLITE_OPEN_NOMUTEX、SQLITE_OPEN_FULLMUTEX、SQLITE_OPEN_SHAREDCACHE、SQLITE_OPEN_PRIVATECACHE、SQLITE_OPEN_URIフラグと組み合わせることができます。

SQLITE_OPEN_READONLYデータベースは読み取り専用モードで開かれます。データベースが存在しない場合は、エラーが返されます。

SQLITE_OPEN_READWRITEデータベースは、可能な場合は読み取りおよび書き込み用に、またはファイルがオペレーティングシステムによって書き込み保護されている場合のみ読み取り用に開かれます。どちらの場合も、データベースはすでに存在している必要があり、そうでない場合はエラーが返されます。

SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATEデータベースは読み取りおよび書き込み用に開かれ、まだ存在しない場合は作成されます。これは、sqlite3_open()およびsqlite3_open16()で常に使用される動作です。

便宜上、通常のパスをsqlite.connect()で使用可能なURIに変換するためのPython 3.4+関数もあります:

import pathlib
import urllib.parse

def _path_to_uri(path):
    path = pathlib.Path(path)
    if path.is_absolute():
        return path.as_uri()
    return 'file:' + urllib.parse.quote(path.as_posix(), safe=':/')
3

これはフォークです(Python 3を使用)Tom Horenの回答に基づいており、選択された回答よりも完全で信頼性の高いソリューションを提供します。

選出された回答は、ファイル、SQLite3データベースに関連するデータが実際に含まれているかどうかを判断するために、コンテンツやヘッダーなどを評価しません。

ここでより実用的なものを提示しようとしました:

#!/usr/bin/python3

import os
import sys

if os.path.isfile('test.sqlite3'):
    if os.path.getsize('test.sqlite3') > 100:
        with open('test.sqlite3','r', encoding = "ISO-8859-1") as f:
            header = f.read(100)
            if header.startswith('SQLite format 3'):
                print("SQLite3 database has been detected.")
1
ivanleoncz