如何检查Python中是否存在SQLite3数据库?

如何检查Python中是否存在SQLite3数据库?,python,python-2.7,sqlite,Python,Python 2.7,Sqlite,我试图在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

我试图在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)
这样的文件操作?

在Python 2中,必须使用以下方法显式测试数据库是否存在:

无法强制
sqlite3.connect
函数不为您创建文件


对于那些使用Python3.4或更新版本的用户,可以使用更新的URI路径功能在打开数据库时设置不同的模式。默认情况下,
sqlite3.connect()

使用URI,您可以指定不同的模式;如果将其设置为
rw
,则在尝试连接到不存在的数据库时会引发异常。连接时设置
uri=True
标志并传入
文件:
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
有关接受哪些参数的详细信息,请参阅。

os.path.isfile()
只是告诉您是否存在文件,而不是它是否存在并且是SQLite3数据库!要知道,您可以这样做:

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'

我在脚本的开头使用了如下函数,这样我就可以尝试找出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
这是一个基于Tom Horen的答案的fork(使用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.")

是的,有一种方法可以使用Python 3.4+实现您想要的功能

使用
sqlite3.connect()
函数进行连接,但向其传递URI而不是文件路径,并将
mode=rw
添加到其查询字符串中

下面是一个完整的工作代码示例:

导入sqlite3 con=sqlite3.connect('file:aaa.db?mode=rw',uri=True)
这将从当前文件夹中名为
aaa.db
的文件中打开现有数据库,但如果该文件无法打开或不存在,则会引发错误:

回溯(最近一次呼叫最后一次):
文件“aaa.py”,第2行,在
con=sqlite3.connect('file:aaa.db?mode=rw',uri=True)
sqlite3.0错误:无法打开数据库文件
Python声明:

若uri为true,则将数据库解释为uri。这允许您指定选项。例如,要以只读模式打开数据库,可以使用:

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

有关此功能的更多信息,包括已识别选项的列表,请参见

以下是从以下网站收集的所有相关URI选项信息的摘录:

模式:模式参数可设置为“ro”、“rw”、“rwc”或“内存”。尝试将其设置为任何其他值都是错误的。如果指定了“ro”,则数据库将以只读访问方式打开,就像在sqlite3\u OPEN\u v2()的第三个参数中设置了SQLITE\u READONLY标志一样。如果mode选项设置为“rw”,则数据库将打开进行读写(但不创建)访问,就像已设置SQLITE_OPEN_READWRITE(但不设置SQLITE_OPEN_create)一样。值“rwc”相当于设置SQLITE_OPEN_READWRITE和SQLITE_OPEN_CREATE。如果mode选项设置为“memory”,则使用从不从磁盘读取或写入的纯内存数据库。为mode参数指定的值的限制性小于在第三个参数中传递给sqlite3_open_v2()的标志所指定的值是错误的

sqlite3\u open\u v2()接口的工作原理与sqlite3\u open()类似,只是它接受两个附加参数,用于对新数据库连接进行附加控制。sqlite3_open_v2()的flags参数可以采用以下三个值之一,可以选择与SQLITE_open_NOMUTEX、SQLITE_open_FULLMUTEX、SQLITE_open_SHAREDCACHE、SQLITE_open_PRIVATECACHE和/或SQLITE_open_URI标志组合使用:

SQLITE\u打开\u只读 数据库以只读模式打开。如果数据库不存在,则返回一个错误

SQLITE\u打开\u读写 如果可能,将打开数据库进行读写,或者仅当文件受操作系统写保护时才进行读写。在这两种情况下,数据库必须已经存在,否则将返回错误

SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE 将打开数据库进行读写操作,如果数据库尚不存在,则会创建该数据库。这是sqlite3_open()和sqlite3_open16()始终使用的行为

为了方便起见,这里还有一个Python 3.4+函数,用于将常规路径转换为sqlite.connect()可用的URI:

导入路径库
导入urllib.parse
定义路径到uri(路径):
path=pathlib.path(路径)
如果path.is_absolute():
返回路径。as_uri()
返回“file:”+urllib.parse.quote(path.as_posix(),safe=”:/)

建立在上述两个其他答案的基础上。下面是一个在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')
def isSqlite3Db(db):
如果不是os.path.isfile(db):返回
#!/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.")
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