2010-09-01 10 views
52

J'utilise Python et MySQLdb pour télécharger des pages web et les stocker dans la base de données. Le problème que j'ai est que je ne peux pas enregistrer des chaînes compliquées dans la base de données parce qu'elles ne sont pas correctement échappées.Escape string Python pour MySQL

Existe-t-il une fonction en Python que je peux utiliser pour échapper une chaîne pour MySQL? J'ai essayé avec ''' (guillemets simples triples) et """, mais cela n'a pas fonctionné. Je sais que PHP a mysql_escape_string(), est quelque chose de similaire en Python?

Merci.

+0

Do 'db_cur.execute ('' 'MISE À JOUR test_table SET champ_1 = "% s" Où Champ_2 ="% s "'' '% (data, condition))' Notez les guillemets simples et les doubles guillemets autour de '% s' – zelusp

Répondre

75
conn.escape_string() 

Voir MySQL C mappage de fonction API: http://mysql-python.sourceforge.net/MySQLdb.html

+1

+1 ... Réponse parfaite. Surpris de voir autant de réponses compliquées là-bas. De toute évidence, les requêtes param'ed ne tiennent pas compte des longues chaînes (texte) qui sont stockées. – Mike

+0

+1 J'aime les pages HTML en noir et blanc avec des mots et du code jurés. – Droogans

+2

_mysql.escape_string ("input's") peut également fonctionner pour échapper une chaîne ascii pour mysql. Apparemment pas pour unicode cependant. _mysql.escape_string (u "input's é") –

1

Utilisez la fonction texte sqlalchemy pour supprimer l'interprétation des caractères spéciaux:

Notez l'utilisation de la fonction text("your_insert_statement") ci-dessous. Ce qu'il fait est de communiquer à sqlalchemy que tous les points d'interrogation et les signes de pourcentage dans la chaîne passée doivent être considérés comme des littéraux.

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

Vous voulez dire la fonction? – User

+0

Oui, corrigé. –

+0

Est-ce que cela fonctionne pour échapper à des guillemets simples? – user2654569

44

La bibliothèque MySQLdb fera réellement pour vous, si vous utilisez leurs mises en œuvre pour construire une chaîne de requête SQL au lieu d'essayer de construire votre propre.

Ne pas faire:

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)) 
+3

Un peu bouleversant qu'il force les guillemets. Par exemple, si vous insériez dans une table conditionnelle (TABLE_A au lieu de 'TABLE_A'), vous ne pouviez pas le faire complètement avec cette méthode. – bozdoz

+2

bozdoz, cela est très à la conception car il empêche SQL Injection. Si vous souhaitez insérer dans une table conditionnelle, assurez-vous d'abord qu'une chaîne soumise par l'utilisateur ne peut pas être utilisée pour le nom de la table, puis ajoutez-la directement à la requête. – techdude

+1

C'est certainement la bonne réponse. Ne savez jamais quelles nouvelles façons d'éviter les fuites de chaînes (comme nous le faisons actuellement dans le monde PHP ...). Il est toujours préférable de faire des déclarations préparées –

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. On dirait que l'algorithme de mise en évidence de StackOverflows ne connaît pas les guillemets de Python. –