Escape-строка Python для MySQL

Я использую Python и MySQLdb для загрузки веб-страниц и сохранения их в базе данных. У меня проблема в том, что я не могу сохранить сложные строки в базе данных, потому что они не экранированы должным образом.

Есть ли функция в Python, которую я могу использовать для экранирования строки для MySQL? Я пробовал использовать ''' (тройные простые кавычки) и """, но это не сработало. Я знаю, что в PHP есть mysql_escape_string(), есть ли что-то подобное в Python?

Спасибо.


person Laurențiu Dascălu    schedule 01.09.2010    source источник
comment
Сделайте db_cur.execute('''UPDATE test_table SET field_1="%s" WHERE field_2="%s"''' % (data, condition)) Обратите внимание на тройные одинарные и двойные кавычки вокруг %s   -  person zelusp    schedule 29.10.2016
comment
Старый поток, но не должен ли последний знак % в вашем коде быть запятой ,, иначе это то же самое? @zelusp   -  person Artemis    schedule 15.07.2019
comment
Нет, я думаю, что это правильно - если вы не запустили мой код, и я ошибаюсь. % (data, condition) берет переменные data и condition и помещает их в два заполнителя %s.   -  person zelusp    schedule 15.07.2019
comment
Это просто форматирование строки Python, которое заменяет. Если бы condition было, например, " or 1 == 1 or" , например, у вас была бы проблема. cur.execute обеспечивает побег, выполнив cur.execute('SOME COMMAND ?', [value]). ? заменяется значением.   -  person Artemis    schedule 21.07.2019


Ответы (7)



Библиотека MySQLdb на самом деле сделает это за вас, если вы будете использовать их реализации для построения строки SQL-запроса вместо того, чтобы пытаться создать свою собственную.

Не делайте:

sql = "INSERT INTO TABLE_A (COL_A,COL_B) VALUES (%s, %s)" % (val1, val2)
cursor.execute(sql)

Do:

sql = "INSERT INTO TABLE_A (COL_A,COL_B) VALUES (%s, %s)"
cursor.execute(sql, (val1, val2))
person User    schedule 19.12.2014
comment
Несколько расстраивает, что это заставляет кавычки. Например, если вы выполняли вставку в условную таблицу (TABLE_A вместо «TABLE_A»), вы не могли сделать это полностью с помощью этого метода. - person bozdoz; 11.05.2015
comment
bozdoz, это сделано специально, поскольку предотвращает SQL-инъекцию. Если вы хотите выполнить вставку в условную таблицу, сначала убедитесь, что введенная пользователем строка не может быть использована для имени таблицы, а затем просто добавьте ее непосредственно в запрос. - person techdude; 08.10.2016
comment
Это определенно правильный ответ. Никогда не знаешь, какие новые способы будут существовать, чтобы обойти экранирование строк (как мы сейчас делаем в мире PHP...). Просто безопаснее всегда делать подготовленные операторы - person Brian Leishman; 09.06.2017
comment
Построитель форматирует, используя точно такой же вызов для db.literal, что и escape, поэтому называть его более безопасным немного неправильно. Используйте его, потому что это проще для небольших запросов, но не беспокойтесь, что вы что-то упускаете, когда вам приходится создавать большой запрос или сценарий вручную. - person c z; 30.04.2019

Используйте текстовую функцию sqlalchemy, чтобы удалить интерпретацию специальных символов:

Обратите внимание на использование функции text("your_insert_statement") ниже. Что он делает, так это сообщает sqlalchemy, что все вопросительные знаки и знаки процента в переданной строке следует рассматривать как литералы.

import sqlalchemy
from sqlalchemy import text
from sqlalchemy.orm import sessionmaker
from datetime import datetime
import re

engine = sqlalchemy.create_engine("mysql+mysqlconnector://%s:%s@%s/%s"
     % ("your_username", "your_password", "your_hostname_mysql_server:3306",
     "your_database"),
     pool_size=3, pool_recycle=3600)

conn = engine.connect()

myfile = open('access2.log', 'r')
lines = myfile.readlines()

penguins = []
for line in lines:
   elements = re.split('\s+', line)

   print "item: " +  elements[0]
   linedate = datetime.fromtimestamp(float(elements[0]))
   mydate = linedate.strftime("%Y-%m-%d %H:%M:%S.%f")

   penguins.append(text(
     "insert into your_table (foobar) values('%%%????')"))

for penguin in penguins:
    print penguin
    conn.execute(penguin)

conn.close()
person Eric Leschinski    schedule 19.11.2014

Еще один способ обойти это — использовать что-то подобное при использовании mysqlclient в python.

предположим, что данные, которые вы хотите ввести, похожи на эти <ol><li><strong style="background-color: rgb(255, 255, 0);">Saurav\'s List</strong></li></ol>. Он содержит как двойные кавычки, так и одинарные кавычки.

Вы можете использовать следующий метод, чтобы избежать кавычек:

оператор = """ Обновить набор чатов html='{}' """.format(html_string.replace("'","\\\'"))

Примечание: три символа \ необходимы, чтобы избежать одинарной кавычки, которая есть в неформатированной строке Python.

person Saurav Panda    schedule 05.04.2020

установить пакет sqlescapy:

pip install sqlescapy

тогда вы можете избежать переменных в своем необработанном запросе

from sqlescapy import sqlescape

query = """
    SELECT * FROM "bar_table" WHERE id='%s'
""" % sqlescape(user_input)
person ELOUAJIB Imad    schedule 13.09.2019
comment
Обратите внимание, что sqlescapy не экранирует должным образом кавычки или двойные кавычки, он просто удаляет их: github.com/elouajib/sqlescapy/blob/master/sqlescapy/ - person Jesús A. Álvarez; 13.03.2020

{!a} применяет ascii() и, следовательно, экранирует не-ASCII-символы, такие как кавычки и даже смайлики. Вот пример

cursor.execute("UPDATE skcript set author='{!a}',Count='{:d}' where url='{!s}'".format(authors),leng,url))

документация по Python3

person Agnel Vishal    schedule 13.10.2018
comment
Ссылка на вашу примерную программу не работает, а одинарные кавычки - ascii - person Tim Richardson; 13.02.2019

person    schedule
comment
Хм. Похоже, что алгоритм выделения StackOverflows не знает тройных кавычек Python. - person Martin Thoma; 03.08.2017
comment
Это особенно полезно для использования в подпрограммах, где строка SQL строится по частям. - person Andrew Basile; 13.05.2018
comment
Форк MySQLdb для Python3: github.com/PyMySQL/mysqlclient-python - person Ian Mackinnon; 23.10.2020