not all arguments converted during string formatting 解决

来源:互联网 发布:安庆网络问政 编辑:程序博客网 时间:2024/05/08 15:41

* error:not all arguments converted during string formatting *


  • 先把解决办法奉上:传入单个参数的时候把param 换成 tuple :(param,) 或者换成list : [param]

  • 用python操作数据库的时候,使用MySQLdb遇到一个问题,是这样的:execute方法传入单个参数,一直报错not all arguments converted during string formatting
with DBHelper as db:    pid = 10010    db.fetch_tuple_as_list("SELECT `name` FROM `vien_table` WHERE `id` = %s LIMIT 1", pid)
with DBHelper as db:    names = [(a),(b),(c)]    db.update_batch("INSERT INTO `vien_table`(`name`) VALUES(%s)", names)
  • DBHelper的两个方法fetch_tuple_as_list、update_batch:
def fetch_dict_as_list(self, sql, params = None):        if not self._dcursor:            self._dcursor = self.get_cursor(MySQLdb.cursors.DictCursor)        try:            self._dcursor.execute(sql, params)            self._current_cursor = self._dcursor            res = self._dcursor.fetchall()            if res:                return list(res)        except Exception as e:            print self.get_time(),'Unable to get results !',e        return Nonedef update_batch(self,sql,items,stepsize = 1000):        if not self._tcursor:            self._tcursor = self.get_cursor()        try:            size = int(stepsize)            length = len(items)            size = size if length >= size else length            print size            for i in xrange(0, (length + size - 1) / size):                self._tcursor.executemany(sql,items[i*size:(i+1)*size])                self._current_cursor = self._tcursor                if self._autocommit:                    self._conn.commit()            return True        except Exception as e:            if self._autocommit:                self._conn.rollback()            print self.get_time(),'Unable to update !\n',e        return False

可以看到,其实最后我调用的是MySQLdb的execute和executemany方法。而错误的位置就在这里,参数转换的时候没有执行成功。

MySQLdb/cursors.py line 187:query = query % tuple([db.literal(item) for item in args])

上述是源码,可以看到这里其实就是将所有传入参数遍历,然后对每一个item用literal处理,literal函数其实就是对item进行转义,然后在加上引号作为字符串以便MySQL识别。例如str = "low's" , sql = ' SELECT * FROM table where name = %s ' % str 这种情况下最后的sql是SELECT * FROM table where name = low's 这样就会给MySQL造成困惑,而不能执行,最简单的方法就是给%s加上引号,像这样"%s" ,然后给str转义,像这样 low\'s。这样我们交给MySQL的就是SELECT * FROM table where name = "low\'s"'。而其实literal就是做了这样一件事,它会把low’s变成’low\\’s’,之所以是 \\ 是因为它先转\ 然后交给MySQL的就是low\’s了,正好满足需求。

言归正传,由于execute是把你传入的参数当成一个Iterator来遍历了,如果你只是传入一个简单的参数,就会造成convert失败,所以如何解决呢?可能你现在就可以想到了,那我传入一个tuple。没错,这个是可以的,但是你会不会直接这样用呢execute(sql,('vien')),如果是这样那你就错了,可以试一下输出type(('vien')),你会发现结果不是tuple而是string!Python官方文档是这样解释的:如果tuple只有一个值,那么不会被当做是tuple,而是这个值的类型。所以你要用tuple怎么用呢,很简单,加个逗号:('vien',) 这样就会被当成是tuple了,当然你也可以将它变成list,list就简单多了,直接['vien'] 就好了。所以我给这个DBHelper加了个方法,来处理这种情况:

def format_param(self,param,batch = False):        if param:            if batch:                return [i if (isinstance(i,tuple) or isinstance(i,list)) else [i] for i in param]            (isinstance(param,tuple) or isinstance(param,list)) and param or [param]        return None

这样问题就解决了。

0 0
原创粉丝点击