PyMySQL
PyMySQL is a pure-Python MySQL client library, fully compliant with PEP 249 (Python Database API Specification v2.0). It enables Python applications to connect to MySQL and MariaDB databases without requiring binary extensions. The library is actively maintained, with version 1.1.2 released on August 24, 2025, and supports standard DB-API 2.0 features like cursors, transactions, and parameterized queries.
Warnings
- breaking PyMySQL 1.0.0 introduced several backward-incompatible changes, dropping support for Python 2.7 and 3.5. `connect()` arguments became keyword-only, and the `db` and `passwd` parameters were deprecated in favor of `database` and `password` respectively. Support for the `old_password` authentication method was also removed.
- breaking As of PyMySQL 1.1.1, `Cursor.execute()` explicitly prohibits dictionary parameters to prevent potential SQL injection vulnerabilities. Passing a dictionary directly will raise an error.
- deprecated The direct access to error classes via the `Cursor` object (e.g., `cursor.Error`) will be removed after June 2024. Also, `Connection.set_charset(charset)` and the usage of `db` and `passwd` parameters in `connect()` will emit `DeprecationWarning`s.
- gotcha By default, PyMySQL connections are not in autocommit mode. Changes made via `INSERT`, `UPDATE`, or `DELETE` statements will not be saved to the database unless `connection.commit()` is explicitly called. Closing a connection without committing will result in a rollback of uncommitted changes.
- gotcha PyMySQL does not provide built-in connection pooling. For applications requiring efficient connection management in multi-threaded or high-concurrency environments, external libraries such as `DBUtils.PooledDB` or `pymysql-pool` are necessary to avoid overhead from frequent connection establishment and teardown.
- gotcha The "MySQL server has gone away" error (`pymysql.err.OperationalError: (2006, 'MySQL server has gone away')`) is a common issue often caused by long idle connections timing out, large query packets exceeding server limits, or network interruptions. This can happen if the Python application holds a connection longer than the MySQL server's `wait_timeout` setting.
Install
-
pip install PyMySQL -
pip install PyMySQL[rsa] -
pip install PyMySQL[ed25519]
Imports
- pymysql
import pymysql
- pymysql.cursors
import pymysql.cursors
Quickstart
import pymysql.cursors
import os
# Configure connection details (replace with your actual database info or environment variables)
host = os.environ.get('MYSQL_HOST', 'localhost')
user = os.environ.get('MYSQL_USER', 'root')
password = os.environ.get('MYSQL_PASSWORD', 'your_password')
database = os.environ.get('MYSQL_DATABASE', 'testdb')
try:
# Connect to the database
connection = pymysql.connect(host=host,
user=user,
password=password,
database=database,
charset='utf8mb4',
cursorclass=pymysql.cursors.DictCursor)
print(f"Successfully connected to MySQL database: {database}")
with connection.cursor() as cursor:
# Example: Create a new record
sql = "INSERT INTO `users` (`email`, `password`) VALUES (%s, %s)"
cursor.execute(sql, ('webmaster@example.com', 'super_secret'))
# connection is not autocommit by default. So you must commit to save your changes.
connection.commit()
print(f"Inserted {cursor.rowcount} row(s).")
# Example: Read a single record
sql = "SELECT `id`, `email`, `password` FROM `users` WHERE `email`=%s"
cursor.execute(sql, ('webmaster@example.com',))
result = cursor.fetchone()
print(f"Fetched record: {result}")
except pymysql.Error as e:
print(f"Error connecting or querying MySQL: {e}")
finally:
if 'connection' in locals() and connection.open:
connection.close()
print("Database connection closed.")