error:not all arguments converted during string formatting 解决

2019-02-16 09:09:12   错误异常

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 None

def 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[isize:(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



> 这样问题就解决了。
vien.tech版权所有,允许转载,但转载请注明出处和原文链接: https://vien.tech/article/60
欢迎小伙伴们在下方评论区留言 ~ O(∩_∩)O
文章对我有帮助, 点此请博主吃包辣条 ~ O(∩_∩)O

猜你喜欢


评论

There are no comments yet.
未登录

登录后即可发表评论

登录或注册