Подтвердить что ты не робот

Python MySQLdb TypeError: не все аргументы, преобразованные во время форматирования строки

После запуска этого script:

#! /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")

Я получаю сообщение об ошибке:

./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

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

4b9b3361

Ответ 1

Вместо этого:

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

Попробуй это:

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

См. Документацию по MySQLdb. Смысл заключается в том, что execute второй параметр представляет собой список объектов, должны быть преобразованы, потому что вы можете иметь произвольное число объектов в параметризованных запросов. В этом случае у вас есть только один, но он все равно должен быть итерируемым (кортеж вместо списка тоже будет прекрасен).

Ответ 2

Вы можете попробовать этот код:

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

Вы можете увидеть документацию

Ответ 3

Ключевое слово

'%' настолько опасно, что является основной причиной "SQL INJECTION ATTACK".
Таким образом, вы просто используете этот код.

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

или

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

если вы хотите попробовать вставить в таблицу, попробуйте это.

name = 'ksg'
age = 19
sex = 'male'
t  = (name, age, sex)
cursor.execute("insert into table values(%s,%d,%s)", t)

Ответ 4

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

Я не понимаю, но это работает для меня. вместо использования '%s'.

Ответ 5

Я не понимаю первые два ответа. Я думаю, что они должны быть зависимыми от версии. Я не могу воспроизвести их на MySQLdb 1.2.3, который поставляется с Ubuntu 14.04LTS. Попробуй их. Во-первых, мы проверяем, что MySQL не принимает двойные апострофы:

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

Неа. Попробуйте пример, который обязательный отправил с помощью конструктора запросов внутри /usr/lib/python2.7/dist-packages/MySQLdb/cursors.py, где я открыл "con" в качестве подключения к моей базе данных.

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

Нет, двойные апострофы заставляют его терпеть неудачу. Давайте попробуем первый комментарий Майка Грэма, где он предлагает оставить апострофы, цитируя% s:

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

Да, это сработает, но второй комментарий Майка и документация говорят, что аргумент для выполнения (обрабатываемый con.literal) должен быть кортежем (search,) или списком [search]. Вы можете попробовать их, но вы не найдете отличий от вышеприведенного вывода.

Лучший ответ - ksg97031's.

Ответ 6

В соответствии с PEP8 я предпочитаю выполнять SQL таким образом:

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)

Таким образом, вы поймете, что второй аргумент args метода execute должен быть списком аргументов.

Пусть это поможет вам.

Ответ 7

Принятый ответ by @kevinsa5 правильный, но вы можете подумать: "Я клянусь, что этот код работал, а теперь это не так", и вы были бы правы.

В библиотеке MySQLdb между 1.2.3 и 1.2.5 произошло изменение API. Поддерживаемые версии 1.2.3

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

но версии 1.2.5 требуют

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

как утверждают другие ответы. Я не могу найти изменения в списках изменений, и, возможно, более раннее поведение считалось ошибкой.

Репозиторий Ubuntu 14.04 имеет python-mysqldb 1.2.3, но Ubuntu 16.04 и более поздние версии имеют python-mysqldb 1.3. 7+.

Если вы имеете дело с устаревшей базой кода, которая требует старого поведения, но ваша платформа является новым Ubuntu, вместо этого установите MySQLdb из PyPI:

$ pip install MySQL-python==1.2.3

Ответ 8

Я столкнулся с этой ошибкой при выполнении SELECT * FROM table; Я проследил ошибку до курсора строки 195.

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

Учитывая, что я ввожу какие-либо дополнительные параметры, я избавился от всей ветки "if args...". Теперь это работает.