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

时间:2014-02-12 21:43:35

标签: python python-2.7

运行此脚本时:

#! /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有些新意,所以这可能是一个明显的问题。

7 个答案:

答案 0 :(得分:76)

而不是:

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

试试这个:

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

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

答案 1 :(得分:16)

您可以尝试以下代码:

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

您可以看到the documentation

答案 2 :(得分:2)

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

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

答案 3 :(得分:0)

我不理解前两个答案。我认为它们必须依赖于版本。我无法在MySQLdb 1.2.3上重现它们,它随Ubuntu 14.04LTS一起提供。我们来试试吧。首先,我们验证MySQL不接受双撇号:

/usr/lib/python2.7/dist-packages/MySQLdb/cursors.py

不。让我们尝试使用>>> search = "test" >>> "SELECT * FROM records WHERE email LIKE '%s'" % con.literal(search) "SELECT * FROM records WHERE email LIKE ''test''" >>> 里面的查询构造函数强制发布的示例,其中我打开了#34; con&#34;作为我数据库的连接。

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

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

(search,)

是的,这会有效,但Mike的第二条评论和文档说要执行的参数(由con.literal处理)必须是元组[search]或列表{{1}} 。你可以尝试一下,但是你发现上面的输出没有区别。

最好的答案是ksg97031&#39。

答案 4 :(得分:0)

根据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必须是参数列表。

这可以帮助你。

答案 5 :(得分:0)

@ 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,请从PyPI安装MySQLdb:

$ pip install MySQL-python==1.2.3

答案 6 :(得分:0)

我在执行时遇到此错误 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))

鉴于我要输入任何其他参数,所以我摆脱了所有“ if args ...”分支。现在可以了。