Как проверить наличие базы данных SQLite3 в Python?

Я пытаюсь создать функцию в 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)?

Ответ 1

В Python 2 вам нужно будет явно проверить существование с помощью os.path.isfile:

if os.path.isfile(db):

sqlite3.connect функцию sqlite3.connect не создавать файл для вас.


Для тех, кто использует Python 3.4 или новее, вы можете использовать новую функцию пути URI, чтобы установить другой режим при открытии базы данных. Функция sqlite3.connect() по умолчанию будет открывать базы данных в rwc, то есть режиме Read, Write & Create, поэтому подключение к несуществующей базе данных приведет к ее созданию.

Используя URI, вы можете указать другой режим; если вы установите его на rw, поэтому режим чтения и записи, возникает исключение при попытке подключиться к несуществующей базе данных. Вы можете установить разные режимы, когда вы устанавливаете флаг uri=True при подключении и передаче в file: URI и добавляете параметр mode=rw query к пути:

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.

Ответ 2

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

Ответ 3

Да, есть способ сделать то, что вы хотите, с 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 истинно, база данных интерпретируется как URI. Это позволяет указать параметры. Например, чтобы открыть базу данных в режиме только для чтения, вы можете использовать:

db = sqlite3.connect('file: путь /to/database? mode = ro', uri = True)

Более подробную информацию об этой функции, включая список распознанных опций, можно найти в документации SQLite URI.

Здесь выдержка из всей соответствующей информации о параметрах URI, собранной с http://www.sqlite.org/c3ref/open.html:

mode: параметр режима может быть установлен как "ro", "rw", "rwc" или "memory". Попытка установить его на любое другое значение - ошибка. Если указано "ro", тогда база данных открывается для доступа только для чтения, как если бы флаг SQLITE_OPEN_READONLY был установлен в третьем аргументе sqlite3_open_v2(). Если для параметра режима установлено значение "rw", база данных открывается для чтения и записи (но не создается), как если бы не было установлено SQLITE_OPEN_READWRITE (но не SQLITE_OPEN_CREATE). Значение "rwc" эквивалентно установке SQLITE_OPEN_READWRITE и SQLITE_OPEN_CREATE. Если для параметра mode установлено значение "memory", тогда используется чистая база данных в памяти, которая никогда не читает или не записывает с диска. Ошибочно указывать значение параметра mode, которое является менее ограничительным, чем значение, указанное флажками, переданными третьим параметром, в sqlite3_open_v2().

Интерфейс sqlite3_open_v2() работает как sqlite3_open(), за исключением того, что он принимает два дополнительных параметра для дополнительного контроля над новым подключением к базе данных. Параметр flags для sqlite3_open_v2() может принимать одно из следующих трех значений, необязательно в сочетании с битами 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+ для преобразования обычного пути в URI, который можно использовать с помощью sqlite.connect():

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=':/')

Ответ 4

Это вилка (с использованием 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.")

Ответ 5

Я использую функцию, подобную следующей в начале моего скрипта, чтобы попытаться выяснить, почему скрипт 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