# Connector/Python Guide

### Quickstart Guide: MariaDB Connector/Python

MariaDB Connector/Python is the official Python client library for connecting applications to MariaDB and MySQL databases. It implements the Python DB API 2.0 (PEP-249) standard, ensuring compatibility with common Python database programming patterns.

**Version 2.0** offers flexible distribution options:

* **Pure Python** - Works everywhere, no compiler or dependencies required
* **C extension** - Maximum performance (2-12× faster on data-heavy workloads)
* **Pre-compiled wheels** - No MariaDB Connector/C installation needed
* **Async/await support** - Native asynchronous operations for modern Python applications

## API Reference

* [**Connection API**](https://mariadb.com/docs/connectors/mariadb-connector-python/api/connection) - Connection parameters, methods, and attributes
* [**Cursor API**](https://mariadb.com/docs/connectors/mariadb-connector-python/api/cursor) - Cursor parameters, methods, and attributes
* [**Connection Pooling API**](https://mariadb.com/docs/connectors/mariadb-connector-python/pooling) - Pool configuration and usage

#### 1. Prerequisites

Before installing MariaDB Connector/Python, ensure you have:

* **Python:** Version 3.9 or later
* **MariaDB Connector/C:** Version 3.3.1 or later (optional - only required for C extension from source)

#### 2. Installation

Choose the installation option that best fits your needs:

**Pure Python (recommended for most users):**

```bash
pip install mariadb
```

**Pre-compiled binary wheels (best for production):**

```bash
pip install mariadb[binary,pool]
```

**C extension from source (maximum performance):**

```bash
# Requires MariaDB Connector/C installed
pip install mariadb[c,pool]
```

#### 3. Basic Usage

Here's a simple Python example demonstrating how to connect to MariaDB, execute queries, and manage transactions.

**Using Dictionary Configuration (All Versions):**

```python
import mariadb
import sys

# 1. Database Connection Configuration
db_config = {
    'host': 'localhost',
    'port': 3306,
    'user': 'your_username',
    'password': 'your_password',
    'database': 'your_database_name'
}

def run_db_operations():
    conn = None
    cursor = None
    try:
        # 2. Establish a Connection
        print("Connecting to MariaDB...")
        conn = mariadb.connect(**db_config)
        print("Connection successful!")

        # 3. Create a Cursor Object
        cursor = conn.cursor()

        # ... (rest of the code continues below)
```

**Using URI Connection String (Since Version 2.0):**

```python
import mariadb
import sys

# 1. Database Connection URI (Available since MariaDB Connector/Python 2.0)
DATABASE_URL = "mariadb://your_username:your_password@localhost:3306/your_database_name"

def run_db_operations():
    conn = None
    cursor = None
    try:
        # 2. Establish a Connection
        print("Connecting to MariaDB...")
        conn = mariadb.connect(DATABASE_URL)
        print("Connection successful!")

        # 3. Create a Cursor Object
        cursor = conn.cursor()

        # --- Example: Create a Table (if it doesn't exist) ---
        try:
            cursor.execute("""
                CREATE TABLE IF NOT EXISTS users (
                    id INT AUTO_INCREMENT PRIMARY KEY,
                    name VARCHAR(255) NOT NULL,
                    email VARCHAR(255) UNIQUE
                )
            """)
            conn.commit() # Commit the transaction for DDL
            print("Table 'users' created or already exists.")
        except mariadb.Error as e:
            print(f"Error creating table: {e}")
            conn.rollback() # Rollback in case of DDL error

        # --- Example: Insert Data (Parameterized Query) ---
        print("\nInserting data...")
        insert_query = "INSERT INTO users (name, email) VALUES (?, ?)"
        try:
            cursor.execute(insert_query, ("Alice Wonderland", "alice@example.com"))
            cursor.execute(insert_query, ("Bob Builder", "bob@example.com"))
            conn.commit() # Commit the transaction for DML
            print(f"Inserted {cursor.rowcount} rows.")
            print(f"Last inserted ID: {cursor.lastrowid}")
        except mariadb.IntegrityError as e:
            print(f"Error inserting data (might be duplicate email): {e}")
            conn.rollback()
        except mariadb.Error as e:
            print(f"Error inserting data: {e}")
            conn.rollback()

        # --- Example: Select Data ---
        print("\nSelecting data...")
        select_query = "SELECT id, name, email FROM users WHERE name LIKE ?"
        cursor.execute(select_query, ("%Alice%",)) # Note the comma for single parameter tuple
        
        print("Fetched data:")
        for row in cursor:
            print(f"ID: {row[0]}, Name: {row[1]}, Email: {row[2]}")

        # --- Example: Update Data ---
        print("\nUpdating data...")
        update_query = "UPDATE users SET name = ? WHERE email = ?"
        cursor.execute(update_query, ("Alicia Wonderland", "alice@example.com"))
        conn.commit()
        print(f"Rows updated: {cursor.rowcount}")

        # --- Example: Delete Data ---
        print("\nDeleting data...")
        delete_query = "DELETE FROM users WHERE name = ?"
        cursor.execute(delete_query, ("Bob Builder",))
        conn.commit()
        print(f"Rows deleted: {cursor.rowcount}")

    except mariadb.Error as e:
        print(f"An error occurred: {e}")
        sys.exit(1)
    finally:
        # 4. Close Cursor and Connection
        if cursor:
            cursor.close()
            print("Cursor closed.")
        if conn:
            conn.close()
            print("Connection closed.")

if __name__ == "__main__":
    run_db_operations()
```

**Before Running:**

1. Replace `your_username`, `your_password`, and `your_database_name` with your actual MariaDB server credentials.
2. Ensure you have a MariaDB server running and the specified database exists.
3. The example assumes `your_table_name` is `users` with columns `id`, `name`, `email`. Adjust the table/column names as needed.

#### Important Notes:

* **Parameterized Queries:** Always use parameterized queries (e.g., `VALUES (?, ?)`) to prevent SQL injection vulnerabilities. Parameters are passed as a tuple or list to the `execute()` method.
* **Transactions (`conn.commit()` / `conn.rollback()`):** By default, autocommit is disabled. Call `conn.commit()` to save changes or `conn.rollback()` to undo them.
* **Error Handling:** Use `try...except mariadb.Error` blocks to gracefully handle database-related exceptions.
* **Resource Management:** Always close your `cursor` and `connection` objects in a `finally` block to ensure resources are released, even if errors occur.
* **URI Connections:** Version 2.0 supports standard URI connection strings for cleaner configuration.
* **Binary Protocol:** Use `binary=True` for prepared statements and better performance with repeated queries.

#### 4. Async/Await Support (New in 2.0)

For modern async applications (FastAPI, Starlette, etc.):

```python
import asyncio
import mariadb

async def async_operations():
    # Connect asynchronously
    conn = await mariadb.asyncConnect(
        "mariadb://your_username:your_password@localhost/your_database_name"
    )
    
    try:
        cursor = await conn.cursor()
        
        # Execute async query
        await cursor.execute("SELECT id, name, email FROM users WHERE id = ?", (1,))
        user = await cursor.fetchone()
        print(f"User: {user}")
        
        await cursor.close()
    finally:
        await conn.close()

# Run async function
asyncio.run(async_operations())
```

**Async Connection Pool:**

```python
import asyncio
import mariadb

async def main():
    # Create async pool
    pool = await mariadb.create_async_pool(
        "mariadb://user:password@localhost/mydb",
        min_size=5,
        max_size=20
    )
    
    # Use pool
    async with await pool.acquire() as conn:
        async with conn.cursor() as cursor:
            await cursor.execute("SELECT COUNT(*) FROM users")
            count = (await cursor.fetchone())[0]
            print(f"Total users: {count}")
    
    await pool.close()

asyncio.run(main())
```

#### Further Resources:

* [PyPI MariaDB Connector/Python](https://pypi.org/project/mariadb/)
* [MariaDB Connector/Python Documentation](https://mariadb-corporation.github.io/mariadb-connector-python/)
* [Migration Guide (1.1 to 2.0)](https://mariadb-corporation.github.io/mariadb-connector-python/migration-from-1.1-to-2.0.html)
* [Async/Await Support](https://mariadb-corporation.github.io/mariadb-connector-python/async-usage.html)
* [MariaDB Developers Python Quickstart (GitHub)](https://github.com/mariadb-developers/python-quickstart)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://mariadb.com/docs/connectors/connectors-quickstart-guides/connector-python-guide.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
