it-swarm.com.de

Python MySQLdb TypeError: Nicht alle während der String-Formatierung konvertierten Argumente

Beim Ausführen dieses Skripts:

#! /usr/bin/env python
import MySQLdb as mdb
import sys    

class Test:
    def check(self, search):
        try:
            con = mdb.connect('localhost', 'root', 'password', 'recordsdb');

            cur = con.cursor()
            cur.execute( "SELECT * FROM records WHERE email LIKE '%s'", search )

            ver = cur.fetchone()

            print "Output : %s " % ver

        except mdb.Error, e:

            print "Error %d: %s" % (e.args[0],e.args[1])
            sys.exit(1)

        finally:    
            if con:    
                con.close()

test = Test()
test.check("test")

Ich bekomme einen Fehler von:

./lookup 
Traceback (most recent call last):
  File "./lookup", line 27, in <module>
    test.check("test")
  File "./lookup", line 11, in creep
    cur.execute( "SELECT * FROM records WHERE email LIKE '%s'", search )
  File "/usr/local/lib/python2.7/dist-packages/MySQLdb/cursors.py", line 187, in execute
    query = query % Tuple([db.literal(item) for item in args])
TypeError: not all arguments converted during string formatting

Ich habe keine Ahnung warum. Ich versuche, parametrisierte Abfragen zu machen, aber es war nur ein Schmerz. Ich bin etwas neu in Python, daher ist es wahrscheinlich ein offensichtliches Problem.

36

An Stelle von:

cur.execute( "SELECT * FROM records WHERE email LIKE '%s'", search )

Versuche dies:

cur.execute( "SELECT * FROM records WHERE email LIKE %s", [search] )

Siehe die MySQLdb Dokumentation . Der Grund ist, dass der zweite Parameter von execute eine Liste der zu konvertierenden Objekte darstellt, da in einer parametrisierten Abfrage eine beliebige Anzahl von Objekten vorhanden sein könnte. In diesem Fall haben Sie nur einen, aber es muss noch ein Iterer sein (ein Tupel anstelle einer Liste wäre auch in Ordnung). 

74
kevinsa5

Sie können diesen Code ausprobieren:

cur.execute( "SELECT * FROM records WHERE email LIKE '%s'", (search,) )

Sie können die Dokumentation sehen

16

Das '%'-Schlüsselwort ist so gefährlich, weil es die Hauptursache für' SQL INJECTION ATTACK 'ist. 
Sie verwenden also einfach diesen Code.

cursor.execute("select * from table where example=%s", (example,))

oder

t = (example,)
cursor.execute("select * from table where example=%s", t)

wenn Sie versuchen möchten, Einfügen in eine Tabelle, versuchen Sie dies.

name = 'ksg'
age = 19
sex = 'male'
t  = (name, age, sex)
cursor.execute("insert into table values(%s,%d,%s)", t)
6
ksg97031
cur.execute( "SELECT * FROM records WHERE email LIKE %s", (search,) )

Ich weiß nicht warum, aber das funktioniert für mich. Verwenden Sie nicht '%s'.

2
bob90937

Dieser Fehler ist bei der Ausführung von SELECT * FROM table; .__ aufgetreten. Ich habe den Fehler in der Zeile "Cursor.py" 195 festgestellt. 

if args is not None:
        if isinstance(args, dict):
            nargs = {}
            for key, item in args.items():
                if isinstance(key, unicode):
                    key = key.encode(db.encoding)
                nargs[key] = db.literal(item)
            args = nargs
        else:
            args = Tuple(map(db.literal, args))
        try:
            query = query % args
        except TypeError as m:
            raise ProgrammingError(str(m))

In Anbetracht der Tatsache, dass ich zusätzliche Parameter eingebe, wurde der gesamte Zweig "if args ..." entfernt. Jetzt gehts. 

0
Adel

Die akzeptierte Antwort von @ kevinsa5 ist richtig, aber Sie denken vielleicht "Ich schwöre diesen Code verwendet um zu funktionieren und jetzt funktioniert es nicht", und Sie hätten recht.

In der MySQLdb-Bibliothek wurde zwischen 1.2.3 und 1.2.5 eine API-Änderung vorgenommen. Die 1.2.3-Versionen werden unterstützt

cursor.execute("SELECT * FROM foo WHERE bar = %s", 'baz')

aber die 1.2.5-Versionen erfordern

cursor.execute("SELECT * FROM foo WHERE bar = %s", ['baz'])

wie die anderen Antworten angeben. Ich kann die Änderung in den Änderungsprotokollen nicht finden und es ist möglich, dass das frühere Verhalten als Fehler angesehen wurde.

Das Repository von Ubuntu 14.04 enthält Python-mysqldb 1.2.3, Ubuntu 16.04 und höher jedoch Python-mysqldb 1.3.7 und höher.

Wenn Sie eine alte Codebase verwenden, die das alte Verhalten erfordert, Ihre Plattform jedoch ein neuartiges Ubuntu ist, installieren Sie stattdessen MySQLdb von PyPI:

$ pip install MySQL-python==1.2.3
0
user4851

Ich verstehe die ersten beiden Antworten nicht. Ich denke, dass sie versionsabhängig sein müssen. Ich kann sie nicht auf MySQLdb 1.2.3, das mit Ubuntu 14.04LTS geliefert wird, reproduzieren. Lass es uns versuchen. Zunächst überprüfen wir, dass MySQL keine Doppel-Apostrophe akzeptiert:

mysql> select * from methods limit 1;
+----------+--------------------+------------+
| MethodID | MethodDescription  | MethodLink |
+----------+--------------------+------------+
|       32 | Autonomous Sensing | NULL       |
+----------+--------------------+------------+
1 row in set (0.01 sec)

mysql> select * from methods where MethodID = ''32'';
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 '9999'' ' at line 1

Nee. Versuchen wir das Beispiel, das obligatorisch mit dem Abfragekonstruktor in /usr/lib/python2.7/dist-packages/MySQLdb/cursors.py gepostet wurde, in dem ich "con" als Verbindung zu meiner Datenbank geöffnet habe.

>>> search = "test"
>>> "SELECT * FROM records WHERE email LIKE '%s'" % con.literal(search)
"SELECT * FROM records WHERE email LIKE ''test''"
>>> 

Nein, die doppelten Apostrophe führen dazu, dass es versagt. Versuchen wir es mit Mike Grahams erstem Kommentar, in dem er vorsieht, die Apostrophe wegzulassen und die% s zu zitieren:

>>> "SELECT * FROM records WHERE email LIKE %s" % con.literal(search)
"SELECT * FROM records WHERE email LIKE 'test'"
>>> 

Ja, das wird funktionieren, aber Mikes zweiter Kommentar und die Dokumentation besagen, dass das auszuführende Argument (von con.literal verarbeitet) ein Tuple (search,) oder eine Liste [search] sein muss. Sie können sie ausprobieren, aber Sie werden keinen Unterschied zur obigen Ausgabe finden.

Die beste Antwort lautet ksg97031.

0
Russell Nelson

Nach PEP8 prefer bevorzuge ich es, SQL auf diese Weise auszuführen:

cur = con.cursor()
# There is no need to add single-quota to the surrounding of `%s`,
# because the MySQLdb precompile the sql according to the scheme type
# of each argument in the arguments list.
sql = "SELECT * FROM records WHERE email LIKE %s;"
args = [search, ]
cur.execute(sql, args)

Auf diese Weise erkennen Sie, dass das zweite Argument args der Methode execute eine Liste von Argumenten sein muss.

Möge das dir helfen.

0
stillzhl