web-dev-qa-db-fra.com

Comment vérifier si une base de données SQLite3 existe en Python?

J'essaie de créer une fonction dans Python 2.7.3 pour ouvrir une base de données SQLite.

Ceci est mon code pour le moment:

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]

J'ai essayé le code ci-dessus et j'ai constaté que la bibliothèque sqlite3 ouvrait la base de données déclarée si elle existait ou créait une nouvelle base de données si celle-ci n'existait pas.

Existe-t-il un moyen de vérifier si la base de données existe avec les méthodes sqlite3 ou si je dois utiliser une opération de fichier telle que os.path.isfile(path)?

15
maxim

En Python 2, vous devrez explicitement tester l'existence à l'aide de os.path.isfile :

if os.path.isfile(db):

Il n'y a aucun moyen de forcer la fonction sqlite3.connect à ne pas créer le fichier pour vous.


Pour ceux qui utilisent Python 3.4 ou une version plus récente, vous pouvez utiliser la fonctionnalité de chemin d'accès URI la plus récente pour définir un mode différent lors de l'ouverture d'une base de données. La fonction sqlite3.connect() ouvre par défaut les bases de données en rwc, c'est-à-dire Lecture, écriture et création mode, de sorte que la connexion à une base de données non existante provoque sa création.

En utilisant un URI, vous pouvez spécifier un mode différent à la place. si vous le définissez sur rw, so Read & Write mode, une exception est générée lors de la tentative de connexion à une base de données non existante. Vous pouvez définir différents modes lorsque vous définissez l'indicateur uri=True lors de la connexion et transmettez un URI file:, puis ajoutez un paramètre de requête mode=rw au chemin d'accès:

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

Voir le SQLite URI Paramètres de requête reconnus documentation pour plus de détails sur les paramètres acceptés.

22
Martijn Pieters

os.path.isfile() vous indique simplement si un fichier existe, pas s'il existe ET est une base de données SQLite3! En connaissant http://www.sqlite.org/fileformat.html , vous pouvez le faire:

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'

et ensuite l'utiliser comme:

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
16
Tom Horen

Oui, il existe un moyen de faire ce que vous voulez avec Python 3.4+.

Utilisez la fonction sqlite3.connect() pour vous connecter, mais transmettez-lui un URI au lieu d’un chemin de fichier et ajoutez mode=rw à sa chaîne de requête.

Voici un exemple de code de travail complet:

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

Cela ouvrira une base de données existante à partir d'un fichier nommé aaa.db dans le dossier actuel, mais générera une erreur si ce fichier ne peut pas être ouvert ou n'existe pas:

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 déclarez que:

Si uri est true, la base de données est interprétée comme un URI. Cela vous permet de spécifier des options. Par exemple, pour ouvrir une base de données en mode lecture seule, vous pouvez utiliser:

db = sqlite3.connect ('fichier: chemin/de/base de données? mode = ro', uri = True)

Vous trouverez plus d'informations sur cette fonctionnalité, y compris une liste des options reconnues, dans Documentation de l'URI SQLite .

Voici un extrait de toutes les informations d'option URI pertinentes collectées à partir de http://www.sqlite.org/c3ref/open.html :

mode : Le paramètre mode peut être réglé sur "ro", "rw", "rwc" ou "memory". Tenter de lui attribuer une autre valeur est une erreur. Si "ro" est spécifié, la base de données est ouverte pour un accès en lecture seule, comme si l'indicateur SQLITE_OPEN_READONLY avait été défini dans le troisième argument de sqlite3_open_v2 (). Si l'option mode est définie sur "rw", la base de données est ouverte pour un accès en lecture-écriture (mais pas pour la création), comme si SQLITE_OPEN_READWRITE (mais pas SQLITE_OPEN_CREATE) avait été défini. La valeur "rwc" équivaut à définir SQLITE_OPEN_READWRITE et SQLITE_OPEN_CREATE. Si l'option mode est définie sur "memory", une base de données pure en mémoire qui ne lit ni n'écrit jamais à partir du disque est utilisée. C'est une erreur de spécifier pour le paramètre mode une valeur moins restrictive que celle spécifiée par les indicateurs passés dans le troisième paramètre à sqlite3_open_v2 ().

L'interface sqlite3_open_v2 () fonctionne comme sqlite3_open () sauf qu'elle accepte deux paramètres supplémentaires pour un contrôle supplémentaire sur la nouvelle connexion à la base de données. Le paramètre flags de sqlite3_open_v2 () peut prendre l'une des trois valeurs suivantes, éventuellement combiné avec les drapeaux SQLITE_OPEN_NOMUTEX, SQLITE_OPEN_FULLMUTEX, SQLITE_OPEN_SHAREDCACHE, SQLITE_OPEN_PRIVATECACHE et/ou SQLITE_OPEN_URI.

SQLITE_OPEN_READONLY La base de données est ouverte en lecture seule. Si la base de données n'existe pas déjà, une erreur est renvoyée.

SQLITE_OPEN_READWRITE La base de données est ouverte en lecture et en écriture si possible, ou en lecture uniquement si le fichier est protégé en écriture par le système d'exploitation. Dans les deux cas, la base de données doit déjà exister, sinon une erreur est renvoyée.

SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE La base de données est ouverte en lecture et en écriture et est créée si elle n'existe pas déjà. C'est le comportement qui est toujours utilisé pour sqlite3_open () et sqlite3_open16 ().

Pour plus de commodité, voici également une fonction Python 3.4+ permettant de convertir un chemin normal en un URI utilisable par 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=':/')
1
Jurko Gospodnetić

Ceci est un fork (utilisant Python 3) basé sur la réponse de Tom Horen , qui présente une solution plus complète et fiable que la réponse choisie. 

La réponse choisie n'évalue aucun contenu, en-tête, etc., afin de déterminer si le fichier contient ou non des données relatives à une base de données SQLite3.

J'ai essayé de présenter quelque chose de plus pragmatique ici:

#!/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.")
0
ivanleoncz