MySQLdb批量執行sql, TypeError: not all arguments converted during string formatting

  • 1.錯誤代碼

    import MySQLdb
    if __name__ == '__main__':
        dbItem={}
        dbItem['host']='127.0.0.1'
        dbItem['port']=3306
        dbItem['user']='root'
        dbItem['password']='123456'
        dbItem['database']='test'
        dbItem['charset']='utf8'
        dbItem['use_unicode']='False'
    
        conn = MySQLdb.connect(host=dbItem.get('host'), port=dbItem.get('port', 3306),
                               user=dbItem.get('user'), passwd=dbItem.get('password'),
                               db=dbItem.get('database'), charset=dbItem.get('charset'),
                               use_unicode=dbItem.get('use_unicode'))
        cursor = conn.cursor()
    
        # 初始數據,第一個值爲表名的一部分
        list = [('classify', 130, 'classify1'),('content',14,'markdownContent')]
        insertsql = '''insert into atc_%s(id,data) values(%s, %s)'''
    
        "---這裏報錯---"
        cursor.executemany(insertsql, tuple(list))
    
        conn.close()
    
  • 2.錯誤信息:TypeError: not all arguments converted during string formatting

  • 3.查看executemany方法源碼

        def executemany(self, query, args):
            del self.messages[:]
            db = self._get_db()
            if not args: return
            charset = db.character_set_name()
            if isinstance(query, unicode): query = query.encode(charset)
    	"---!!重點就在這裏---"
            m = insert_values.search(query)
            if not m:
                r = 0
                for a in args:
                    r = r + self.execute(query, a)
                return r
            p = m.start(1)
            e = m.end(1)
            qv = m.group(1)
            try:
                q = [ qv % db.literal(a) for a in args ]
            except TypeError, msg:
                if msg.args[0] in ("not enough arguments for format string",
                                   "not all arguments converted"):
                    self.errorhandler(self, ProgrammingError, msg.args[0])
                else:
                    self.errorhandler(self, TypeError, msg)
            except:
                exc, value, tb = sys.exc_info()
                del tb
                self.errorhandler(self, exc, value)
            r = self._query('\n'.join([query[:p], ',\n'.join(q), query[e:]]))
            if not self._defer_warnings: self._warning_check()
            return r
    

    找到關鍵點所在,m = insert_values.search(query)

    import re
    restr = (r"\svalues\s*"
            r"(\(((?<!\\)'[^\)]*?\)[^\)]*(?<!\\)?'"
            r"|[^\(\)]|"
            r"(?:\([^\)]*\))"
            r")+\))")
    # 全部變量
    insert_values= re.compile(restr)
    ...
    # executemany方法中
    m = insert_values.search(query)
    

    這段代碼的意思就是:截取出sql語句中values之後的字符串。
    我上面的代碼截取到的就應該是:values(%s, %s)
    以上代碼有疑惑的同學:傳送門1傳送門2

  • 4.解決方法
    問題出在哪裏顯而易見了,executemany方法中設置參數時沒有截取到values之前的字段,導致參數個數與%s個數對不上。

    將表名和要插入的數據封裝成字典,再進行批量插入即可。修改後的代碼:

    import MySQLdb
    if __name__ == '__main__':
        dbItem={}
        ...
        conn = MySQLdb.connect(host=dbItem.get('host'), port=dbItem.get('port', 3306),
                               user=dbItem.get('user'), passwd=dbItem.get('password'),
                               db=dbItem.get('database'), charset=dbItem.get('charset'),
                               use_unicode=dbItem.get('use_unicode'))
        cursor = conn.cursor()
    
        # 初始數據,第一個值爲表名的一部分
        list = [('classify', 130, 'classify1'),('content',14,'markdownContent')]
    
        # 封裝成字典數據結構
        value_dic = {}
        for item in list:
            valList = []
            tbName = item[0]
            if value_dic.has_key(tbName):
                valList = value_dic.get(tbName)
            valList.append(item[1:])
            value_dic[tbName] = valList
       
        # 分數據表批量執行
        for tbName,valList in value_dic.items():
            insertsql = '''insert into atc_{tbName}(id,data) values(%s, %s)'''.format(tbName=tbName)
            cursor.executemany(insertsql, tuple(valList))
    
        conn.close()
    
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章