ZetCode

Python sqlite3.connect Function

Last modified April 15, 2025

This comprehensive guide explores Python's sqlite3.connect function, the primary way to interact with SQLite databases. We'll cover basic usage, connection parameters, isolation levels, and practical examples.

Basic Definitions

The sqlite3.connect function establishes a connection to an SQLite database. It creates a new database file if one doesn't exist or opens an existing one.

Key characteristics: it returns a connection object, accepts various parameters to control behavior, and manages transactions. The connection is the gateway for all database operations in SQLite.

Basic Database Connection

Here's the simplest usage of sqlite3.connect to create or open a database file and perform basic operations.

basic_connect.py
import sqlite3

# Connect to database (creates if doesn't exist)
with sqlite3.connect('example.db') as conn:
    cursor = conn.cursor()
    
    # Create a table
    cursor.execute('''CREATE TABLE IF NOT EXISTS users
                      (id INTEGER PRIMARY KEY, name TEXT, age INTEGER)''')
    
    # Insert data
    cursor.execute("INSERT INTO users (name, age) VALUES (?, ?)", ('Alice', 30))
    
    # Commit is automatic with context manager

This example shows the basic workflow using a context manager. The database file 'example.db' is created in the current directory if it doesn't exist.

The with statement ensures the connection is properly closed and changes are committed automatically when the block exits successfully.

Using Connection with Cursor as Context Manager

Both connection and cursor can be used as context managers for cleaner resource management.

cursor_context.py
import sqlite3

with sqlite3.connect('example.db') as conn:
    with conn.cursor() as cursor:
        cursor.execute("SELECT * FROM users")
        rows = cursor.fetchall()
        for row in rows:
            print(row)

This example demonstrates nested context managers for both connection and cursor. The cursor is automatically closed when its block exits.

This pattern is especially useful when working with multiple cursors or complex transaction sequences, ensuring all resources are properly released.

In-Memory Database with Context Manager

SQLite supports in-memory databases which are fast but temporary, perfect for testing.

memory_context.py
import sqlite3

with sqlite3.connect(':memory:') as conn:
    with conn.cursor() as cursor:
        cursor.execute('''CREATE TABLE test 
                          (id INTEGER, data TEXT)''')
        cursor.execute("INSERT INTO test VALUES (1, 'Sample')")
        cursor.execute("SELECT * FROM test")
        print(cursor.fetchone())  # (1, 'Sample')

The special :memory: filename creates a database in RAM. It's much faster than disk-based databases but disappears when the connection closes.

The context manager ensures the in-memory database is properly cleaned up even if an error occurs during operations.

Connection with Isolation Level

The isolation_level parameter controls SQLite's transaction behavior. This example shows how to use different isolation levels with context managers.

isolation_context.py
import sqlite3

# Connect with explicit isolation level
with sqlite3.connect('transactions.db', 
                    isolation_level='IMMEDIATE') as conn:
    with conn.cursor() as cursor:
        cursor.execute("UPDATE accounts SET balance = balance - 100 WHERE id = 1")
        cursor.execute("UPDATE accounts SET balance = balance + 100 WHERE id = 2")

This example uses IMMEDIATE isolation level which locks the database immediately on write. The context manager handles commit/rollback automatically.

If any error occurs during the transaction, the context manager will automatically roll back the changes before closing the connection.

Custom Row Factory with Context Manager

The row_factory parameter allows customizing how rows are returned, enabling access by column name.

row_factory_context.py
import sqlite3

with sqlite3.connect('example.db') as conn:
    conn.row_factory = sqlite3.Row  # Built-in row factory
    with conn.cursor() as cursor:
        cursor.execute("SELECT * FROM users LIMIT 1")
        row = cursor.fetchone()
        print(row['name'])  # Access by column name

This example uses SQLite's built-in Row factory that provides named access to columns. The context managers ensure proper cleanup of resources.

Named access improves code readability and maintainability, especially with queries returning many columns or when schema might change.

Connection with Timeout

The timeout parameter specifies how long to wait when a database is locked by another connection.

timeout_context.py
import sqlite3

try:
    # Connect with 5 second timeout
    with sqlite3.connect('busy.db', timeout=5.0) as conn:
        with conn.cursor() as cursor:
            cursor.execute("UPDATE counters SET value = value + 1 WHERE id = 1")
except sqlite3.OperationalError as e:
    print("Database locked beyond timeout:", e)

This connection will wait up to 5 seconds if the database is locked by another process. The context manager handles the connection lifecycle.

The timeout is particularly important in multi-process applications where database contention might occur. The try/except handles timeout errors.

URI Connection with Context Manager

The uri parameter enables advanced connection options through URI format connection strings.

uri_context.py
import sqlite3

# Connect with URI parameters
uri = 'file:app.db?mode=rwc&cache=shared'
with sqlite3.connect(uri, uri=True, timeout=10) as conn:
    with conn.cursor() as cursor:
        cursor.execute("PRAGMA journal_mode=WAL")
        cursor.execute("SELECT * FROM config")
        print(cursor.fetchall())

This example shows a URI connection with mode, cache, and timeout parameters. The context managers ensure proper resource cleanup.

URI connections support many configuration options not available through regular connection strings, providing more control over database behavior.

Best Practices

Source References

Author

My name is Jan Bodnar, and I am a passionate programmer with extensive programming experience. I have been writing programming articles since 2007. To date, I have authored over 1,400 articles and 8 e-books. I possess more than ten years of experience in teaching programming.

List all Python tutorials.