Python MySQLdb TypeError:并非所有参数都在字符串格式化期间转换

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21740359/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-18 23:31:26  来源:igfitidea点击:

Python MySQLdb TypeError: not all arguments converted during string formatting

pythonpython-2.7

提问by Matthew 'mandatory' Bryant

Upon running this 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")

I get an error of:

我收到以下错误:

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

I have zero idea why. I'm trying to do parameterized querys, but it's been nothing but a pain. I'm somewhat new to Python, so it's probably an obvious problem.

我不知道为什么。我正在尝试进行参数化查询,但这只是一种痛苦。我对 Python 有点陌生,所以这可能是一个明显的问题。

采纳答案by kevinsa5

Instead of this:

取而代之的是:

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

Try this:

尝试这个:

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

See the MySQLdb documentation. The reasoning is that execute's second parameter represents a list of the objects to be converted, because you could have an arbitrary number of objects in a parameterized query. In this case, you have only one, but it still needs to be an iterable (a tuple instead of a list would also be fine).

请参阅 MySQLdb文档。原因是 thatexecute的第二个参数表示要转换的对象列表,因为在参数化查询中可以有任意数量的对象。在这种情况下,您只有一个,但它仍然需要是可迭代的(元组而不是列表也可以)。

回答by Mohamed Abd El Raouf

You can try this code:

你可以试试这个代码:

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

You can see the documentation

你可以看文档

回答by ksg97031

'%' keyword is so dangerous because it major cause of 'SQL INJECTION ATTACK'.
So you just using this code.

'%' 关键字非常危险,因为它是导致 'SQL INJECTION ATTACK' 的主要原因。
所以你只需使用此代码。

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

or

或者

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

if you want to try insert into table, try this.

如果你想尝试插入表,试试这个。

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

回答by Russell Nelson

I don't understand the first two answers. I think they must be version-dependent. I cannot reproduce them on MySQLdb 1.2.3, which comes with Ubuntu 14.04LTS. Let's try them. First, we verify that MySQL doesn't accept double-apostrophes:

我不明白前两个答案。我认为它们必须依赖于版本。我无法在 Ubuntu 14.04LTS 附带的 MySQLdb 1.2.3 上复制它们。让我们试试看。首先,我们验证 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

Nope. Let's try the example that Mandatory posted using the query constructor inside /usr/lib/python2.7/dist-packages/MySQLdb/cursors.pywhere I opened "con" as a connection to my database.

不。让我们试试 Mandatory 使用查询构造函数发布的示例,/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''"
>>> 

Nope, the double apostrophes cause it to fail. Let's try Mike Graham's first comment, where he suggests leaving off the apostrophes quoting the %s:

不,双撇号会导致它失败。让我们试试 Mike Graham 的第一条评论,他建议去掉引用 %s 的撇号:

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

Yep, that will work, but Mike's second comment and the documentation says that the argument to execute (processed by con.literal) must be a tuple (search,)or a list [search]. You can try them, but you'll find no difference from the output above.

是的,这会起作用,但是 Mike 的第二条评论和文档说要执行的参数(由 con.literal 处理)必须是 tuple(search,)或 list [search]。您可以尝试它们,但您会发现与上面的输出没有区别。

The best answer is ksg97031's.

最好的答案是ksg97031。

回答by bob90937

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

I do not why, but this works for me . rather than use '%s'.

我不知道为什么,但这对我有用。而不是使用'%s'.

回答by stillzhl

According PEP8,I prefer to execute SQL in this way:

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

In this way, you will recognize that the second argument argsof executemethod must be a list of arguments.

通过这种方式,你将认识到,第二个参数argsexecute方法必须的参数列表。

May this helps you.

愿这对你有帮助。

回答by user4851

The accepted answer by @kevinsa5 is correct, but you might be thinking "I swear this code usedto work and now it doesn't," and you would be right.

@kevinsa5 接受的答案是正确的,但您可能会想“我发誓这段代码曾经可以工作,但现在不能了”,您是对的。

There was an API change in the MySQLdb library between 1.2.3 and 1.2.5. The 1.2.3 versions supported

MySQLdb 库中的 API 在 1.2.3 和 1.2.5 之间发生了变化。支持的 1.2.3 版本

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

but the 1.2.5 versions require

但 1.2.5 版本需要

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

as the other answers state. I can't find the change in the changelogs, and it's possible the earlier behavior was considered a bug.

正如其他答案所述。我在更改日志中找不到更改,并且可能将较早的行为视为错误。

The Ubuntu 14.04 repository has python-mysqldb 1.2.3, but Ubuntu 16.04 and later have python-mysqldb 1.3.7+.

Ubuntu 14.04 存储库具有 python-mysqldb 1.2.3,但 Ubuntu 16.04 及更高版本具有 python-mysqldb 1.3.7+。

If you're dealing with a legacy codebase that requires the old behavior but your platform is a newish Ubuntu, install MySQLdb from PyPI instead:

如果您正在处理需要旧行为的旧代码库,但您的平台是新的 Ubuntu,请从 PyPI 安装 MySQLdb:

$ pip install MySQL-python==1.2.3

回答by Adel

I encountered this error while executing SELECT * FROM table;I traced the error to cursor.py line 195.

我在执行时遇到了这个错误, SELECT * FROM table;我将错误追踪到了 cursor.py 第 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))

Given that I am entering any extra parameters, I got rid of all of "if args ..." branch. Now it works.

鉴于我正在输入任何额外的参数,我摆脱了所有“if args ...”分支。现在它起作用了。