Of course! Let's break down addslashes in Python.

What is addslashes?
In Python, addslashes() is a string method that adds a backslash \ character before certain predefined characters that have special meaning in many contexts, most notably in SQL and in string literals.
The characters that are escaped are:
- Single quote:
- Double quote:
- Backslash:
\ - Null character:
\0
This is primarily used as a simple defense against certain types of injection attacks (like SQL injection) and to ensure strings can be safely included in other formats.
The Official Definition
The function is part of the re (regular expressions) module, which might seem odd at first, but it's a historical artifact from Python's early days.

import re help(re.escape)
The official documentation says:
re.escape(string)Escape all non-alphanumeric characters in string. This is useful if you want to match an arbitrary literal string that may have regular expression metacharacters in it.
However, re.escape() is much more aggressive than addslashes. It escapes all non-alphanumeric characters, including spaces, , , etc.

For the specific purpose of escaping quotes and backslashes, you should use a custom function or a library function, as Python does not have a built-in addslashes function like some other languages (e.g., PHP).
How to Use addslashes in Python
Since there's no built-in addslashes, you have a few options.
Option 1: The Manual (and Best) Way - Using str.replace()
For simple cases, you can chain the str.replace() method. This is the most straightforward and Pythonic way if you don't want to add an external dependency.
def addslashes(s):
return s.replace('\\', '\\\\').replace('"', '\\"').replace("'", "\\'")
# --- Examples ---
my_string = "This is a test with 'single quotes' and \"double quotes\"."
escaped_string = addslashes(my_string)
print(f"Original: {my_string}")
print(f"Escaped: {escaped_string}")
Output:
Original: This is a test with 'single quotes' and "double quotes".
Escaped: This is a test with \'single quotes\' and \"double quotes\".
Note: The order of replacements matters. You must escape the backslash (\) first, otherwise, you'll create new backslashes that then need to be escaped.
Option 2: Using the codecs Module
The codecs module has a encode method that can be used to achieve a similar result. It's a bit more cryptic but works well.
import codecs
def addslashes_codecs(s):
return codecs.encode(s, 'unicode_escape').replace("'", "\\'")
# --- Example ---
my_string = "O'Reilly & Co."
escaped_string = addslashes_codecs(my_string)
print(f"Original: {my_string}")
print(f"Escaped: {escaped_string}")
Output:
Original: O'Reilly & Co.
Escaped: O\'Reilly & Co.
unicode_escapeescapes backslashes and quotes. It also escapes newlines (\n), tabs (\t), etc.- We then add an extra replacement for the single quote.
Option 3: Using the mysql-connector-python Library
If you are working with MySQL, the official library provides a function specifically for this purpose.
# First, install the library if you haven't:
# pip install mysql-connector-python
import mysql.connector
def addslashes_mysql(s):
return mysql.connector.conversion.MySQLConverter().escape(s)
# --- Example ---
my_string = "It's dangerous to go alone! '\\'"
escaped_string = addslashes_mysql(my_string)
print(f"Original: {my_string}")
print(f"Escaped: {escaped_string}")
Output:
Original: It's dangerous to go alone! '\'
Escaped: It\'s dangerous to go alone! '\\\\'
This is the most robust method if you are already using this library.
The Crucial Warning: addslashes is NOT Enough for Security
This is the most important part. Using addslashes to prevent SQL injection is NOT recommended and is considered a weak security measure.
Why is it not enough?
The core vulnerability is that the database's character set and connection settings can change the meaning of a backslash.
-
The Magic Quotes Problem (Historical): Some old PHP configurations had "magic quotes" enabled, which would automatically add slashes to incoming data. If your application also added slashes, you'd end up with double-escaped data, breaking your queries.
-
Standard SQL Mode (The Real Problem): In modern MySQL, the standard SQL mode is often enabled. In this mode, backslashes are treated as literal characters, not as escape characters.
-
Your Code (Insecure):
# User input username = "admin'; --" # Your "protection" escaped_username = addslashes(username) # "admin'; --" # The query you build query = "SELECT * FROM users WHERE username = '" + escaped_username + "'" # query becomes: "SELECT * FROM users WHERE username = 'admin'; --'"
-
The Attack: In standard SQL mode, the backslash is just a character. The query is still perfectly valid and will execute, allowing the attacker to bypass your protection. The single quote after the backslash doesn't do anything.
-- The query is interpreted as: SELECT * FROM users WHERE username = 'admin'; --' -- The '--' starts a comment, effectively ignoring the rest of the query. -- This returns the first admin user.
-
The Correct and Secure Way: Parameterized Queries
The industry-standard, secure way to handle user input in database queries is to use parameterized queries (also called prepared statements). This method separates the SQL command from the data, ensuring that data can never be interpreted as code.
Most modern Python database libraries support this.
Example with sqlite3
import sqlite3
# Malicious user input
malicious_input = "admin'; --"
# --- The SECURE way ---
try:
conn = sqlite3.connect(':memory:')
cursor = conn.cursor()
# 1. Define the query with placeholders (?)
query = "SELECT * FROM users WHERE username = ?"
# 2. Execute the query, passing the data as a separate argument
# The library safely escapes the data for you.
cursor.execute(query, (malicious_input,))
results = cursor.fetchall()
print(f"Secure query found {len(results)} results.")
print("The malicious input was treated as a literal string, not a command.")
except sqlite3.Error as e:
print(f"Database error: {e}")
finally:
if conn:
conn.close()
Example with mysql-connector-python
import mysql.connector
# Malicious user input
malicious_input = "admin'; --"
# --- The SECURE way ---
try:
conn = mysql.connector.connect(
host="localhost",
user="your_user",
password="your_password",
database="your_db"
)
cursor = conn.cursor()
# 1. Define the query with placeholders (%s)
query = "SELECT * FROM users WHERE username = %s"
# 2. Execute the query with the data as a tuple
cursor.execute(query, (malicious_input,))
results = cursor.fetchall()
print(f"Secure query found {len(results)} results.")
except mysql.connector.Error as e:
print(f"Database error: {e}")
finally:
if conn.is_connected():
cursor.close()
conn.close()
Summary
| Method | When to Use | Security Level | Notes |
|---|---|---|---|
Manual str.replace() |
Simple string manipulation, not for security. | Low | Good for basic escaping, e.g., in CSV files or config files. |
codecs.encode() |
Simple string manipulation, not for security. | Low | More comprehensive escape than str.replace. |
addslashes() from library |
If you are already using that library. | Low (for SQL) | Avoid for general-purpose security. |
| Parameterized Queries | Always for database interactions. | High | The correct, industry-standard way to prevent SQL injection. |
Final Rule: Use addslashes (or any manual escaping) for formatting strings, but always use parameterized queries for any database interaction to keep your application secure.
