2010-09-01 16 views
52

Używam Pythona i MySQLdb do pobierania stron internetowych i przechowywania ich w bazie danych. Mam problem polegający na tym, że nie mogę zapisać skomplikowanych ciągów w bazie danych, ponieważ nie są one poprawnie usunięte.Escape string Python for MySQL

Czy istnieje funkcja w języku Python, której można użyć do uniknięcia ciągu znaków dla MySQL? Próbowałem z ''' (potrójne proste cytaty) i """, ale to nie zadziałało. Wiem, że PHP ma mysql_escape_string(), jest coś podobnego w Pythonie?

Dzięki.

+0

Czy 'db_cur.execute ('' 'UPDATE test_table SET Pole_1 = "% s", gdzie field_2 ="% s "" "% (dane, warunek))" Zwróć uwagę na potrójne pojedyncze cytaty i podwójne cudzysłowy wokół '% s'' – zelusp

Odpowiedz

75
conn.escape_string() 

See MySQL C mapowanie funkcji API: Funkcja tekst http://mysql-python.sourceforge.net/MySQLdb.html

+1

+1 ... Doskonała odpowiedź. Zaskoczony, widząc tak wiele skomplikowanych odpowiedzi. Oczywiście, zapytania parametryczne nie uwzględniają długich napisów (tekstów), które są przechowywane. – Mike

+0

+1 Uwielbiam czarno-białe strony HTML z przekleństwami i kodem. – Droogans

+2

_mysql.escape_string ("input") może również działać, aby uniknąć ciągu ascii dla mysql. Najwyraźniej nie dla unicode. _mysql.escape_string (u "input's éh") –

1

Skorzystaj sqlalchemy do usunięcia interpretację znaków specjalnych:

Uwaga Użycie funkcji text("your_insert_statement") poniżej. To, co robi, przekazuje sqlalchemy, że wszystkie znaki zapytania i znaki procentowe w przekazanym łańcuchu powinny być traktowane jako literały.

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

engine = sqlalchemy.create_engine("mysql+mysqlconnector://%s:%[email protected]%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() 
+0

Masz na myśli funkcję? – User

+0

Tak, poprawione. –

+0

czy to działa, aby uniknąć pojedynczych cytatów? – user2654569

44

Biblioteka MySQLdb rzeczywiście zrobić dla Ciebie, jeśli używasz ich implementacje zbudować ciąg kwerendy SQL zamiast próbować zbudować własną.

nie rób:

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

zrobić:

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

Nieco niepokoi, że wymusza znaki cudzysłowu. Na przykład, jeśli wstawiłeś do tabeli warunkowej (TABLE_A zamiast "TABLE_A"), nie można tego zrobić całkowicie za pomocą tej metody. – bozdoz

+2

bozdoz, jest to bardzo zgodne z projektem, ponieważ zapobiega iniekcji SQL. Jeśli chcesz wstawić do tabeli warunkowej, najpierw upewnij się, że nie ma możliwości, aby użytkownik podał ciąg znaków dla nazwy tabeli, a następnie po prostu dodaj go bezpośrednio do zapytania. – techdude

+1

To zdecydowanie jest poprawna odpowiedź. Nigdy nie wiadomo, jakie będą nowe sposoby ominięcia ciągu znaków (jak obecnie robimy w świecie PHP ...). Bezpieczniejsze jest robienie przygotowanych oświadczeń zawsze –

3
>>> import MySQLdb 
>>> example = r"""I don't like "special" chars ¯\_(ツ)_/¯""" 
>>> example 
'I don\'t like "special" chars \xc2\xaf\\_(\xe3\x83\x84)_/\xc2\xaf' 
>>> MySQLdb.escape_string(example) 
'I don\\\'t like \\"special\\" chars \xc2\xaf\\\\_(\xe3\x83\x84)_/\xc2\xaf' 
+0

Hm. Wydaje się, że algorytm podświetlania StackOverflows nie zna potrójnych cytatów Pythona. –