Sqlite3.connect: примеры (PYTHON)

Функция sqlite3.connect в Python для работы с SQLite
Раздел: Базы данных, SQLite
sqlite3.connect(database, timeout, detect_types, isolation_level, check_same_thread, factory, cached_statements, uri): sqlite3.Connection

Основные сведения о функции sqlite3.connect

Функция sqlite3.connect() из модуля sqlite3 в Python создает соединение с базой данных SQLite. Она является точкой входа для работы с SQLite в Python-приложениях. Соединение с базой данных необходимо для выполнения любых операций с данными, включая создание таблиц, вставку, обновление, удаление и выборку записей.

Аргументы функции

  • database (строка, bytes или path-like объект) - путь к файлу базы данных или специальное имя, такое как ':memory:' для базы в оперативной памяти.
  • timeout (целое число) - время ожидания в секундах, пока база данных разблокируется перед генерацией исключения. По умолчанию 5.0 секунд.
  • detect_types (целое число) - определяет, выполняется ли автоматическое преобразование типов данных SQLite в типы Python. Может быть комбинацией PARSE_DECLTYPES и PARSE_COLNAMES.
  • isolation_level (строка или None) - управляет режимом изоляции транзакций. Может быть None, 'DEFERRED', 'IMMEDIATE' или 'EXCLUSIVE'.
  • check_same_thread (булево значение) - если True, соединение можно использовать только в потоке, который его создал. По умолчанию True.
  • factory (класс) - пользовательский класс для создания соединений вместо стандартного sqlite3.Connection.
  • cached_statements (целое число) - количество подготовленных SQL-запросов, которые кэшируются в соединении. По умолчанию 100.
  • uri (булево значение) - если True, параметр database интерпретируется как URI. По умолчанию False.

Возвращаемое значение

Функция возвращает объект соединения с базой данных типа sqlite3.Connection. Этот объект предоставляет методы для выполнения SQL-запросов, управления транзакциями и настройки соединения.

Примеры использования sqlite3.connect

Базовое подключение к файлу базы данных

import sqlite3

# Подключение к существующей или создание новой базы данных
conn = sqlite3.connect('example.db')
print(type(conn))
conn.close()

Создание базы данных в оперативной памяти

import sqlite3

# Использование базы данных в оперативной памяти
conn = sqlite3.connect(':memory:')
cursor = conn.cursor()
cursor.execute("CREATE TABLE test (id INTEGER, name TEXT)")
cursor.execute("INSERT INTO test VALUES (1, 'Test')")
conn.commit()
conn.close()
# База данных создана и удалена после закрытия соединения

Подключение с различными параметрами

import sqlite3

# Подключение с указанием нескольких параметров
conn = sqlite3.connect(
    database='test.db',
    timeout=10.0,
    detect_types=sqlite3.PARSE_DECLTYPES,
    isolation_level='EXCLUSIVE',
    check_same_thread=False,
    cached_statements=200
)
print(f"Isolation level: {conn.isolation_level}")
conn.close()
Isolation level: EXCLUSIVE

Использование URI для подключения

import sqlite3

# Подключение с использованием URI
conn = sqlite3.connect('file:test.db?mode=rw', uri=True)
print(f"Connection established: {conn}")
conn.close()
Connection established: 

Похожие функции в Python

Модуль sqlite3

В рамках модуля sqlite3 функция connect является основным методом создания соединений. Альтернативой может быть использование классов-наследников sqlite3.Connection через параметр factory.

ORM-библиотеки

Для работы с SQLite в Python также используются ORM-библиотеки:

  • SQLAlchemy - создает соединения через create_engine() с поддержкой пулинга и продвинутых возможностей.
  • Peewee - использует класс SqliteDatabase для инициализации соединения с базой данных.
  • Django ORM - настраивает соединение через параметры DATABASES в настройках проекта.

ORM-библиотеки предпочтительны в крупных проектах с объектно-ориентированной архитектурой, тогда как sqlite3.connect подходит для простых сценариев и скриптов.

Альтернативы в других языках программирования

JavaScript (Node.js)

const sqlite3 = require('sqlite3').verbose();
const db = new sqlite3.Database('./test.db', (err) => {
    if (err) console.error(err.message);
    console.log('Connected to SQLite database');
});
db.close();
Connected to SQLite database

Java

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class SQLiteExample {
    public static void main(String[] args) {
        Connection conn = null;
        try {
            conn = DriverManager.getConnection("jdbc:sqlite:test.db");
            System.out.println("Connection established");
        } catch (SQLException e) {
            System.out.println(e.getMessage());
        } finally {
            try {
                if (conn != null) conn.close();
            } catch (SQLException e) {
                System.out.println(e.getMessage());
            }
        }
    }
}
Connection established

PHP

<?
$db = new SQLite3('test.db');
echo 'Connected to SQLite database';
$db->close();
?>
Connected to SQLite database

C#

using System.Data.SQLite;

class Program
{
    static void Main()
    {
        SQLiteConnection conn = new SQLiteConnection("Data Source=test.db");
        conn.Open();
        Console.WriteLine("Connection established");
        conn.Close();
    }
}
Connection established

Golang

package main

import (
    "database/sql"
    _ "github.com/mattn/go-sqlite3"
    "log"
)

func main() {
    db, err := sql.Open("sqlite3", "./test.db")
    if err != nil {
        log.Fatal(err)
    }
    defer db.Close()
    log.Println("Connected to SQLite database")
}
2023/10/15 12:00:00 Connected to SQLite database

Основные отличия от реализации в Python включают использование драйверов, интерфейсов и методов управления соединениями, характерных для каждого языка.

Типичные ошибки при использовании sqlite3.connect

Проблемы с доступом к файлу базы данных

import sqlite3

try:
    # Попытка подключения к файлу в защищенной директории
    conn = sqlite3.connect('/root/database.db')
except sqlite3.OperationalError as e:
    print(f"Ошибка: {e}")
Ошибка: unable to open database file

Некорректное использование соединения из разных потоков

import sqlite3
import threading

def query_db():
    cursor = conn.cursor()
    cursor.execute("SELECT 1")

conn = sqlite3.connect('test.db', check_same_thread=True)
# Попытка использования соединения из другого потока
thread = threading.Thread(target=query_db)
thread.start()
thread.join()
sqlite3.ProgrammingError: SQLite objects created in a thread can only be used in that same thread.

Использование закрытого соединения

import sqlite3

conn = sqlite3.connect(':memory:')
conn.close()
# Попытка выполнить запрос после закрытия соединения
try:
    cursor = conn.cursor()
except sqlite3.ProgrammingError as e:
    print(f"Ошибка: {e}")
Ошибка: Cannot operate on a closed database.

Некорректные параметры в URI

import sqlite3

try:
    conn = sqlite3.connect('file:test.db?mode=invalid', uri=True)
except sqlite3.OperationalError as e:
    print(f"Ошибка: {e}")
Ошибка: unable to open database file

Изменения в последних версиях Python

В Python 3.10 добавлена поддержка контекстного менеджера для автоматического закрытия соединения. В Python 3.12 улучшена производительность обработки параметризованных запросов и добавлены новые флаги для настройки поведения соединения.

В версии Python 3.11 улучшена обработка ошибок в транзакциях и добавлена поддержка новых режимов изоляции. Также была оптимизирована работа с большими объемами данных при использовании detect_types.

Начиная с Python 3.9, параметр timeout может принимать значения с плавающей точкой для более точного контроля времени ожидания.

Расширенные примеры использования sqlite3.connect

Создание пользовательского класса соединения

Пример python
import sqlite3

class CustomConnection(sqlite3.Connection):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.execute("PRAGMA foreign_keys = ON")
        self.execute("PRAGMA journal_mode = WAL")
    
    def custom_method(self):
        return "Custom connection method"

# Использование пользовательского класса соединения
conn = sqlite3.connect(':memory:', factory=CustomConnection)
print(conn.custom_method())
cursor = conn.cursor()
cursor.execute("PRAGMA foreign_keys")
print(f"Foreign keys: {cursor.fetchone()[0]}")
conn.close()
Custom connection method
Foreign keys: 1

Работа с различными режимами изоляции

Пример python
import sqlite3

# Сравнение различных уровней изоляции
isolation_levels = [None, 'DEFERRED', 'IMMEDIATE', 'EXCLUSIVE']

for level in isolation_levels:
    conn = sqlite3.connect(':memory:', isolation_level=level)
    cursor = conn.cursor()
    cursor.execute("CREATE TABLE test (id INTEGER PRIMARY KEY, data TEXT)")
    
    # Вставка данных с различными уровнями изоляции
    conn.execute("INSERT INTO test (data) VALUES ('test')")
    
    print(f"Isolation level {level}: autocommit mode - {conn.isolation_level is None}")
    conn.close()
Isolation level None: autocommit mode - True
Isolation level DEFERRED: autocommit mode - False
Isolation level IMMEDIATE: autocommit mode - False
Isolation level EXCLUSIVE: autocommit mode - False

Использование detect_types с пользовательскими адаптерами

Пример python
import sqlite3
import datetime
import pickle

# Регистрация адаптеров для пользовательских типов
sqlite3.register_adapter(datetime.datetime, lambda dt: dt.isoformat())
sqlite3.register_converter("datetime", lambda b: datetime.datetime.fromisoformat(b.decode()))

# Регистрация адаптера для сложных объектов
class ComplexObject:
    def __init__(self, value):
        self.value = value

sqlite3.register_adapter(ComplexObject, lambda obj: pickle.dumps(obj))
sqlite3.register_converter("COMPLEX", lambda b: pickle.loads(b))

# Подключение с использованием detect_types
conn = sqlite3.connect(':memory:', detect_types=sqlite3.PARSE_DECLTYPES)
cursor = conn.cursor()

# Создание таблицы с пользовательскими типами
cursor.execute("""
    CREATE TABLE test (
        id INTEGER PRIMARY KEY,
        created_at datetime,
        complex_data COMPLEX
    )""")

# Вставка данных с пользовательскими типами
now = datetime.datetime.now()
obj = ComplexObject([1, 2, 3])
cursor.execute(
    "INSERT INTO test (created_at, complex_data) VALUES (?, ?)",
    (now, obj)
)
conn.commit()

# Чтение данных
cursor.execute("SELECT created_at, complex_data FROM test WHERE id = 1")
row = cursor.fetchone()
print(f"Created at: {row[0]}, type: {type(row[0])}")
print(f"Complex data: {row[1].value}, type: {type(row[1])}")

conn.close()
Created at: 2023-10-15 12:00:00, type: 
Complex data: [1, 2, 3], type: 

Настройка кэширования подготовленных запросов

Пример python
import sqlite3
import time

# Сравнение производительности с разными размерами кэша
for cache_size in [0, 10, 100, 1000]:
    conn = sqlite3.connect(':memory:', cached_statements=cache_size)
    cursor = conn.cursor()
    cursor.execute("CREATE TABLE test (id INTEGER, value TEXT)")
    
    start_time = time.time()
    for i in range(1000):
        cursor.execute("INSERT INTO test VALUES (?, ?)", (i, f'value_{i}'))
    
    conn.commit()
    end_time = time.time()
    
    print(f"Cache size {cache_size}: {end_time - start_time:.4f} seconds")
    conn.close()
Cache size 0: 0.0451 seconds
Cache size 10: 0.0324 seconds
Cache size 100: 0.0318 seconds
Cache size 1000: 0.0315 seconds

Многопоточное приложение с разделением соединений

Пример python
import sqlite3
import threading
from queue import Queue

# Создание общей базы данных
main_conn = sqlite3.connect('shared.db', check_same_thread=False)
main_conn.execute("CREATE TABLE IF NOT EXISTS counters (thread_id INTEGER, count INTEGER)")
main_conn.commit()
main_conn.close()

def worker(thread_id, results_queue):
    # Каждый поток создает свое соединение
    conn = sqlite3.connect('shared.db', check_same_thread=False)
    cursor = conn.cursor()
    
    for i in range(10):
        cursor.execute(
            "INSERT INTO counters (thread_id, count) VALUES (?, ?)",
            (thread_id, i)
        )
    
    conn.commit()
    
    # Получение результатов для этого потока
    cursor.execute(
        "SELECT COUNT(*) FROM counters WHERE thread_id = ?",
        (thread_id,)
    )
    count = cursor.fetchone()[0]
    results_queue.put((thread_id, count))
    
    conn.close()

# Запуск нескольких потоков
results_queue = Queue()
threads = []

for i in range(5):
    thread = threading.Thread(target=worker, args=(i, results_queue))
    threads.append(thread)
    thread.start()

# Ожидание завершения всех потоков
for thread in threads:
    thread.join()

# Вывод результатов
print("Results:")
while not results_queue.empty():
    thread_id, count = results_queue.get()
    print(f"Thread {thread_id}: {count} records")
Results:
Thread 0: 10 records
Thread 1: 10 records
Thread 2: 10 records
Thread 3: 10 records
Thread 4: 10 records

питон sqlite3.connect function comments

En
Sqlite3.connect Connect to SQLite database