Python mysql ucieczki ze znaków specjalnych


Używam Pythona do wstawiania ciągu znaków w MySQL ze znakami specjalnymi.
Linia do wstawienia wygląda następująco:
macaddress_eth0;00:1E:68:C6:09:A0;macaddress_eth1;00:1E:68:C6:09:A1

To jest SQL:
UPGRADE inventory_server 
set server_mac = macaddress\_eth0\;00\:1E\:68\:C6\:09\:A0\;macaddress\_eth1\;00\:1E\:68\:C6\:09\:A1'
where server_name = 'myhost.fqdn.com

Kiedy robię aktualizację, pojawia się ten błąd:
ERROR 1064 (42000): 
You have an error in your SQL syntax; check the manual that corresponds to your
MySQL server version for the right syntax to use near 'UPGRADE inventory_server
set server_mac = 'macaddress\_eth0\;00\:1E\:68\:C6\:09\' at line 1

Kod Pythona:
sql = 'UPGRADE inventory_server set server_mac = \'%s\' where server_name = \'%s\'' % (str(mydb.escape_string(macs)),host)
print sqltry:
con = mydb.connect(DBHOST,DBUSER,DBPASS,DB);
with con:
cur = con.cursor(mydb.cursors.DictCursor)
cur.execute(sql)
con.commit()
except:
return False

Jak mogę wkleić ten surowy tekst?
Zaproszony:
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

To jeden z powodów, dla których warto używać

powiązanie parametrów
http://www.python.org/dev/peps/pep-0249/#id15
zamiast formatowania parametrów w Pythonie.
Po prostu to zrób:
sql = 'UPGRADE inventory_server set server_mac = %s where server_name = %s'

Następnie:
cur.execute(sql, macs, host)

W ten sposób możesz po prostu potraktować ciąg jako ciąg i pozwolić bibliotece MySQL dowiedzieć się, jak go cytować i uciec.
Ponadto generalnie uzyskujesz lepszą wydajność (ponieważ MySQL może kompilować i buforować pojedyncze zapytanie i używać go ponownie dla różnych wartości parametrów) i unikać

ataki iniekcyjne
http://xkcd.com/327/
SQL (jeden z najczęstszych hacków).
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:


Witamy w świecie formatów kodowania ciągów!
>
TL; dr - preferowaną metodą obsługi cudzysłowów i znaków zmiany znaczenia podczas przechowywania danych w kolumnach MySQL jest użycie zapytań parametrycznych i udostępnienie ich sterownikowi MySQLDatabase. Alternatywnie możesz uniknąć cudzysłowów i ukośników, podwajając je przed wstawieniem.

Pełny przykład na dole linku
>

standardowa aktualizacja SQL
>
<pre class="lang-py prettyprint-override">
# as_json must have escape slashes and quotes doubled
query = """\
UPDATE json_sandbox
SET data = '{}'
WHERE id = 1;
""".format(as_json)with DBConn(*client.conn_args) as c:
c.cursor.execute(query)
c.connection.commit()


sparametryzowana aktualizacja SQL
>
<pre class="lang-py prettyprint-override">
# SQL Driver will do the escaping for you
query = """\
UPDATE json_sandbox
SET data = %s
WHERE id = %s;
"""with DBConn(*client.conn_args) as c:
c.cursor.execute(query, (as_json, 1))
c.connection.commit()


Nieprawidłowy kod JSON SQL
>
{
"abc": 123,
"quotes": "ain't it great",
"multiLine1": "hello\nworld",
"multiLine3": "hello\r\nuniverse\r\n"
}


JSON SQL prawidłowe
>
{
"abc": 123,
"quotes": "ain''t it great",
"multiLine1": "hello\\nworld",
"multiLine3": "hello\\r\\nuniverse\\r\\n"
}


Konwersja Pythona:
>
<pre class="lang-py prettyprint-override">
# must escape the escape characters, so each slash is doubled
# Some MySQL Python libraries also have an escape() or escape_string() method.
as_json = json.dumps(payload) \
.replace("'", "''") \
.replace('\\', '\\\\')


Kompletny przykład
>
<pre class="lang-py prettyprint-override">
import json
import yamlfrom DataAccessLayer.mysql_va import get_sql_client, DBConnclient = get_sql_client()def encode_and_store(payload):
as_json = json.dumps(payload) \
.replace("'", "''") \
.replace('\\', '\\\\') query = """\
UPDATE json_sandbox
SET data = '{}'
WHERE id = 1;
""".format(as_json) with DBConn(*client.conn_args) as c:
c.cursor.execute(query)
c.connection.commit() returndef encode_and_store_2(payload):
as_json = json.dumps(payload) query = """\
UPDATE json_sandbox
SET data = %s
WHERE id = %s;
""" with DBConn(*client.conn_args) as c:
c.cursor.execute(query, (as_json, 1))
c.connection.commit() return
def retrieve_and_decode():
query = """
SELECT * FROM json_sandbox
WHERE id = 1
""" with DBConn(*client.conn_args) as cnx:
cursor = cnx.dict_cursor
cursor.execute(query) rows = cursor.fetchall()
as_json = rows[0].get('data') payload = yaml.safe_load(as_json)
return payloadif __name__ == '__main__': payload = {
"abc": 123,
"quotes": "ain't it great",
"multiLine1": "hello\nworld",
"multiLine2": """
hello
world
""",
"multiLine3": "hello\r\nuniverse\r\n"
}
encode_and_store(payload)
output_a = retrieve_and_decode() encode_and_store_2(payload)
output_b = retrieve_and_decode() print("original: {}".format(payload))
print("method_a: {}".format(output_a))
print("method_b: {}".format(output_b)) print('')
print(output_a['multiLine1']) print('')
print(output_b['multiLine2']) print('\nAll Equal?: {}'.format(payload == output_a == output_b))
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:


Przykład wstawiania surowego tekstu w Pythonie:
>

Utwórz tabelę w MySQL

:
create table penguins(id int primary key auto_increment, msg VARCHAR(4000))


Kod Pythona

:
#!/usr/bin/env python
import sqlalchemy
from sqlalchemy import textengine = sqlalchemy.create_engine( "mysql+mysqlconnector://yourusername:yourpassword@yourhostname.com/your_database")
db = engine.connect()weird_string = "~!@#$%^&*()_+`1234567890-={}|[]\;':\""sql = text('INSERT INTO penguins (msg) VALUES (:msg)')
insert = db.execute(sql, msg=weird_string)db.close()


Uruchom to, poznaj weekend

dane:
select * from penguins1 ~!@#$%^&*()_+`1234567890-={}|[]\;\':"

Żaden z tych znaków nie został zinterpretowany podczas wstawiania.
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Chociaż uważam również, że należy użyć wiązania parametrów, jest jeden taki:
>>> 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'

Aby odpowiedzieć na pytania, Zaloguj się lub Zarejestruj się