23

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

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

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)か?

4

6 に答える 6

34

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

if os.path.isfile(db):

sqlite3.connect関数にファイルを作成しないように強制する方法はありません。


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

URIを使用して、代わりに別のモードを指定できます。読み取りおよび書き込みモードに設定するとrw、存在しないデータベースに接続しようとしたときに例外が発生します。接続時にフラグを設定してURIを渡すときにさまざまなモードを設定し、パスにクエリパラメータを追加できます。uri=Truefile: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

受け入れられるパラメーターの詳細については、SQLiteURI認識クエリパラメーターのドキュメントを参照してください。

于 2012-10-17T10:55:30.033 に答える
26

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
于 2013-03-12T07:45:32.883 に答える
5

はい、Python3.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()のドキュメントには次のように記載されています。

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

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

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

これは、 http://www.sqlite.org/c3ref/open.htmlから収集されたすべての関連するURIオプション情報の抜粋です。

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

sqlite3_open_v2()インターフェイスはsqlite3_open()と同様に機能しますが、新しいデータベース接続をさらに制御するために2つの追加パラメーターを受け入れる点が異なります。sqlite3_open_v2()のflagsパラメーターは、次の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に変換するためのPython3.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=':/')
于 2017-11-17T13:21:35.773 に答える
2

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

選択された回答は、ファイルに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.")
于 2017-09-05T07:01:37.450 に答える
0

上記の他のいくつかの答えに基づいて構築します。これがで機能するクリーンなソリューションですPython 3.7.7

def isSqlite3Db(db):
    if not os.path.isfile(db): return False
    sz = os.path.getsize(db)

    # file is empty, give benefit of the doubt that its sqlite
    # New sqlite3 files created in recent libraries are empty!
    if sz == 0: return True

    # SQLite database file header is 100 bytes
    if sz < 100: return False
    
    # Validate file header
    with open(db, 'rb') as fd: header = fd.read(100)    

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

使用法:

if isSqlite3Db('<path_to_db>'):
    # ... <path_to_db> is a Sqlite 3 DB

ノート:

  • 最近のPythonで作成された新しいsqlite3データベースが長さ0のファイルを作成するため、ファイルサイズが100を超えるという回答は機能しません。
  • ファイルヘッダーを読み取る他の例ではPython 3.7.7、文字列ではなくバイトが返されるため、比較は失敗します。
  • を使用した例では、誤検知が発生したsqlite3.connect(dburl, uri=True)ため、うまくいきませんでした。Python 3.7.7
于 2020-12-06T20:16:44.893 に答える
-2

スクリプトの冒頭で次のような関数を使用しているので、sqlite3dbスクリプトが機能しない理由を理解することができます。コメントが言うように、それは3つのフェーズを使用し、パスが存在するかどうかをチェックし、パスがファイルであるかどうかをチェックし、そのファイルのヘッダーがsqlite3ヘッダーであるかどうかをチェックします。

def checkdbFileforErrors():

    #check if path exists
    try:
        with open('/path/to/your.db'): pass
    except IOError:
        return 1

    #check if path if a file
    if not isfile('/path/to/your.db'):
        return 2

    #check if first 100 bytes of path identifies itself as sqlite3 in header
    f = open('/path/to/your.db', "rx")
    ima = f.read(16).encode('hex')
    f.close()
    #see http://www.sqlite.org/fileformat.html#database_header magic header string
    if ima != "53514c69746520666f726d6174203300": 
        return 3

    return 0
于 2013-09-27T15:19:22.427 に答える