我正在尝试在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)
这样的文件操作?
答案 0 :(得分:23)
在Python 2中,您必须使用os.path.isfile
显式测试存在:
if os.path.isfile(db):
无法强制sqlite3.connect
功能不为您创建文件。
对于那些使用Python 3.4或更高版本的用户,可以使用较新的URI路径功能在打开数据库时设置不同的模式。默认情况下,sqlite3.connect()
功能会在rwc
中打开数据库,即读取,写入&创建模式,因此连接到不存在的数据库将导致它被创建。
使用URI,您可以指定其他模式;如果您将其设置为rw
,那么 Read&写入模式,尝试连接到不存在的数据库时会引发异常。在连接时设置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 URI Recognized Query Parameters documentation。
答案 1 :(得分:17)
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
答案 2 :(得分:1)
是的,有一种方法可以用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(&#39; file:path / to / database?mode = ro&#39;,uri = True)
有关此功能的更多信息,包括已识别选项的列表,可在SQLite URI documentation中找到。
以下是从http://www.sqlite.org/c3ref/open.html收集的所有相关URI选项信息的摘录:
模式:模式参数可以设置为&#34; ro&#34;,&#34; rw&#34;,&#34; rwc&#34;或&# 34;存储器&#34 ;.试图将其设置为任何其他值是一个错误。如果&#34; ro&#34;指定,然后打开数据库以进行只读访问,就像在sqlite3_open_v2()的第三个参数中设置了SQLITE_OPEN_READONLY标志一样。如果mode选项设置为&#34; rw&#34;,则打开数据库以进行读写(但不是create)访问,就像设置了SQLITE_OPEN_READWRITE(但不是SQLITE_OPEN_CREATE)一样。价值&#34; rwc&#34;相当于同时设置SQLITE_OPEN_READWRITE和SQLITE_OPEN_CREATE。如果mode选项设置为&#34; memory&#34;然后使用永远不会从磁盘读取或写入的纯内存数据库。为mode参数指定一个值的错误,该值的限制性比第三个参数中传递给sqlite3_open_v2()的标志的限制要小。
sqlite3_open_v2()接口的作用类似于sqlite3_open(),除了它接受两个附加参数以进一步控制新数据库连接。 sqlite3_open_v2()的flags参数可以采用以下三个值之一,可选择与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()的行为。
为方便起见,这里还有一个Python 3.4+函数,用于将常规路径转换为sqlite.connect()可用的URI:
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 :(得分:0)
这是一个基于 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.")
答案 4 :(得分: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 3.7.7
中返回字节,而不是字符串,因此比较将失败。sqlite3.connect(dburl, uri=True)
的示例在Python 3.7.7
中对我不起作用,因为它会带来误报。答案 5 :(得分:-1)
我在脚本的开头使用了如下所示的函数,以便我可以尝试找出sqlite3 db脚本可能无法正常工作的原因。与评论说的一样,它使用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