Python中MySQLdb和torndb模块对MySQL的断连问题处理

在使用python 对wordpress tag 进行细化代码处理时,遇到了调用MySQLdb模块时的出错,由于错误提示和问题原因相差甚远,查看了N久代码也未发现代码有问题。后来问了下师傅,被告知MySQLdb里有一个断接的坑 ,需要进行数据库重连解决。

一、报错代码及提示

运行出错的代码如下:

import MySQLdb
def getTerm(db,tag):
    cursor = db.cursor()
    query = "SELECT term_id FROM wp_terms where name=%s "
    count = cursor.execute(query,tag)
    rows = cursor.fetchall()
    db.commit()
    #db.close()
    if count:
        term_id = [int(rows[id][0]) for id in range(count)]
        return term_id
    else:return None
def addTerm(db,tag):
    cursor = db.cursor()
    query = "INSERT into wp_terms (name,slug,term_group) values (%s,%s,0)"
    data = (tag,tag)
    cursor.execute(query,data)
    db.commit()
    term_id = cursor.lastrowid
    sql = "INSERT into wp_term_taxonomy (term_id,taxonomy,description) values (%s,'post_tag',%s) "
    value = (term_id,tag)
    cursor.execute(sql,value)
    db.commit()
    db.close()
    return int(term_id)
dbconn = MySQLdb.connect(host='localhost', user='root', passwd='123456', db='361way', port=3306, charset='utf8', init_command='set names utf8')
tags = ['mysql','1111','aaaa','bbbb','ccccc','php','abc','python','java']
tagids = []
for tag in tags:
    termid = getTerm(dbconn,tag)
    if termid:
        print tag, 'tag id is ',termid
        tagids.extend(termid)
    else:
        termid = addTerm(dbconn,tag)
        print 'add tag',tag,'id is ' ,termid
        tagids.append(termid)
print 'tag id is ',tagids

直接可以执行,在第for循环里第二次调用getTerm函数时,报错如下:

Traceback (most recent call last):
 File "a.py", line 40, in <module>
  termid = getTerm(dbconn,tag)
 File "a.py", line 11, in getTerm
  count = cursor.execute(query,tag)
 File "/usr/lib64/python2.6/site-packages/MySQLdb/cursors.py", line 154, in execute
  charset = db.character_set_name()
_mysql_exceptions.InterfaceError: (0, '')

二、解决方法

初始时以为是编码问题了,又细核对了几遍未发现编码有问题,在python代码里也未发现异常。后来问过师傅后,师傅来了句提示:

只看代码有啥用,mysql 的超时时间调长点或捕获异常从连,原因是
cursor. connection 没有关闭
但是socket已经断了
cursor 这个行为不会再建立一次socket的
重新执行一次MysqlDB.connect()
看的有点懵懂,先从mysql 里查看了所有timeout相关的变量

mysql> show GLOBAL VARIABLES like "%timeout%";
+----------------------------+-------+
| Variable_name       | Value |
+----------------------------+-------+
| connect_timeout      | 10  |
| delayed_insert_timeout   | 300  |
| innodb_lock_wait_timeout  | 50  |
| innodb_rollback_on_timeout | OFF  |
| interactive_timeout    | 28800 |
| net_read_timeout      | 30  |
| net_write_timeout     | 60  |
| slave_net_timeout     | 3600 |
| table_lock_wait_timeout  | 50  |
| wait_timeout        | 28800 |
+----------------------------+-------+
10 rows in set (0.00 sec)

发现最小的超时时间是10s ,而我的程序执行起来显然就不了10s 。因为之前查过相关的报错,这里估计这个很可能是另外一个报错:2006,MySQL server has gone away  。即然和这个超时时间应该没关系,那就尝试通过MySQLdb ping测试,如果捕获异常,就再进行重连,修改后的代码为:

#!/usr/bin/python
#coding=utf-8
import MySQLdb
def getTerm(db,tag):
 cursor = db.cursor()
 query = "SELECT term_id FROM wp_terms where name=%s "
 count = cursor.execute(query,tag)
 rows = cursor.fetchall()
 db.commit()
 #db.close()
 if count:
 term_id = [int(rows[id][0]) for id in range(count)]
 print term_id
 return term_id
 else:return None
def addTerm(db,tag):
 cursor = db.cursor()
 query = "INSERT into wp_terms (name,slug,term_group) values (%s,%s,0)"
 data = (tag,tag)
 cursor.execute(query,data)
 db.commit()
 term_id = cursor.lastrowid
 sql = "INSERT into wp_term_taxonomy (term_id,taxonomy,description) values (%s,'post_tag',%s) "
 value = (term_id,tag)
 cursor.execute(sql,value)
 db.commit()
 db.close()
 return int(term_id)
dbconn = MySQLdb.connect(host='localhost', user='root', passwd='123456', db='361way', port=3306, charset='utf8', init_command='set names utf8')
tags = ['mysql','1111','aaaa','bbbb','ccccc','php','abc','python','java']
if __name__ == "__main__":
 tagids = []
 for tag in tags:
 try:
   dbconn.ping()
 except:
  print 'mysql connect have been close'
   dbconn = MySQLdb.connect(host='localhost', user='root', passwd='123456', db='361way', port=3306, charset='utf8', init_command='set names utf8')
 termid = getTerm(dbconn,tag)
 if termid:
  print tag, 'tag id is ',termid
  tagids.extend(termid)
 else:
  termid = addTerm(dbconn,tag)
  print 'add tag',tag,'id is ' ,termid
  tagids.append(termid)
 print 'All tags id is ',tagids

再执行发现竟然OK了,而细看下结果,发现基本上每1-2次getTerm或addTerm函数调用就会打印一次'mysql connect have been close' 。

三、使用torndb模块解决mysql断连问题
1.MySQLdb和torndb的代码样例对比
torndb是facebook开源的一个基于MySQLdb二次封装的一个mysql模块,新封装的这个模块比较小,是一个只有2百多行代码的py文件。虽然代码短,功能确相较MySQLdb简便不少,并且该模块由于增加了reconnect方法和max_idel_time参数,解决了mysql的断连问题。比较下使用原生MySQLdb模块和使用torndb模块的代码:
使用MySQLdb模块的代码

import MySQLdb
def getTerm(db,tag):
    cursor = db.cursor()
    query = "SELECT term_id FROM wp_terms where name=%s "
    count = cursor.execute(query,tag)
    rows = cursor.fetchall()
    db.commit()
    #db.close()
    if count:
        term_id = [int(rows[id][0]) for id in range(count)]
        return term_id
    else:return None
def addTerm(db,tag):
    cursor = db.cursor()
    query = "INSERT into wp_terms (name,slug,term_group) values (%s,%s,0)"
    data = (tag,tag)
    cursor.execute(query,data)
    db.commit()
    term_id = cursor.lastrowid
    sql = "INSERT into wp_term_taxonomy (term_id,taxonomy,description) values (%s,'post_tag',%s) "
    value = (term_id,tag)
    cursor.execute(sql,value)
    db.commit()
    db.close()
    return int(term_id)
def addCTag(db,data):
    cursor = db.cursor()
    query = '''INSERT INTO `wp_term_relationships` (
      `object_id` ,
      `term_taxonomy_id`
      )
      VALUES (
      %s, %s) '''
    cursor.executemany(query,data)
    db.commit()
    db.close()
dbconn = MySQLdb.connect(host='localhost', user='root', passwd='123456', db='361way', port=3306, charset='utf8', init_command='set names utf8')
tags = ['mysql','1111','aaaa','bbbb','ccccc','php','abc','python','java']
tagids = []
for tag in tags:
    if termid:
        try:
         dbconn.ping()
        except:
         dbconn = MySQLdb.connect(host='localhost', user='root', passwd='123456', db='361way', port=3306, charset='utf8', init_command='set names utf8')
         print tag, 'tag id is ',termid
        termid = getTerm(dbconn,tag)
        tagids.extend(termid)
    else:
        try:
         dbconn.ping()
        except:
         dbconn = MySQLdb.connect(host='localhost', user='root', passwd='123456', db='361way', port=3306, charset='utf8', init_command='set names utf8')
        termid = addTerm(dbconn,tag)
        print 'add tag',tag,'id is ' ,termid
        tagids.append(termid)
print 'tag id is ',tagids
postid = '35'
tagids = list(set(tagids))
ctagdata = []
for tagid in tagids:
  ctagdata.append((postid,tagid))
try:
  dbconn.ping()
except:
  dbconn = MySQLdb.connect(host='localhost', user='root', passwd='123456', db='361way', port=3306, charset='utf8', init_command='set names utf8')
  addCTag(dbconn,ctagdata)

使用torndb的代码

#!/usr/bin/python
#coding=utf-8
import torndb
def getTerm(db,tag):
    query = "SELECT term_id FROM wp_terms where name=%s "
    rows = db.query(query,tag)
    termid = []
    for row in rows:
      termid.extend(row.values())
    return termid
def addTerm(db,tag):
    query = "INSERT into wp_terms (name,slug,term_group) values (%s,%s,0)"
    term_id = db.execute_lastrowid(query,tag,tag)
    sql = "INSERT into wp_term_taxonomy (term_id,taxonomy,description) values (%s,'post_tag',%s) "
    db.execute(sql,term_id,tag)
    return term_id
def addCTag(db,data):
    query = "INSERT INTO wp_term_relationships (object_id,term_taxonomy_id) VALUES (%s, %s) "
    db.executemany(query,data)
dbconn = torndb.Connection('localhost:3306','361way',user='root',password='123456')
tags = ['mysql','1111','aaaa','bbbb','ccccc','php','abc','python','java']
tagids = []
for tag in tags:
  termid = getTerm(dbconn,tag)
  if termid:
    print tag, 'tag id is ',termid
    tagids.extend(termid)
  else:
    termid = addTerm(dbconn,tag)
    print 'add tag',tag,'id is ' ,termid
    tagids.append(termid)
print 'All tags id is ',tagids
postid = '35'
tagids = list(set(tagids))
ctagdata = []
for tagid in tagids:
  ctagdata.append((postid,tagid))
addCTag(dbconn,ctagdata)

从两者的代码上来看,使用torndb模块和原生相比,发现可以省略如下两部分:

torndb模块不需要db.cursor进行处理,无不需要db.comment提交,torndb是自动提交的;

torndb不需要在每次调用时,进行db.ping()判断数据库socket连接是否断开,因为torndb增加了reconnect方法,支持自动重连。

2.torndb的方法

torndb提供的参数和方法有:

execute                      执行语句不需要返回值的操作。
execute_lastrowid            执行后获得表id,一般用于插入后获取返回值。
executemany                  可以执行批量插入。返回值为第一次请求的表id。
executemany_rowcount         批量执行。返回值为第一次请求的表id。
get                          执行后获取一行数据,返回dict。
iter                         执行查询后,返回迭代的字段和数据。
query                        执行后获取多行数据,返回是List。
close                        关闭
max_idle_time                最大连接时间
reconnect                    关闭后再连接
使用示例:

mysql> CREATE TABLE `ceshi` (`id` int(1) NULL AUTO_INCREMENT ,`num` int(1) NULL ,PRIMARY KEY (`id`));
>>> import torndb
>>> db = torndb.Connection("127.0.0.1","数据库名","用户名", "密码", 24*3600)  # 24*3600为超时时间
>>> get_id1 = db.execute_lastrowid("insert ceshi(num) values('1')")
>>> print get_id1
1
>>> args1 = [('2'),('3'),('4')]
>>> get1 = db.executemany("insert ceshi(num) values(%s)", args1)
>>> print get1
2
>>> rows = db.iter("select * from ceshi")
>>> for i in rows:
… print i

3.报错

在使用过程中可能遇到的错误:

 File "/home/361way/database.py", line 145, in execute_lastrowid
  self._execute(cursor, query, parameters)
 File "/home/361way/database.py", line 207, in _execute
  return cursor.execute(query, parameters)
 File "/usr/lib/pymodules/python2.7/MySQLdb/cursors.py", line 159, in execute
  query = query % db.literal(args)
TypeError: not enough arguments for format string

写上面的代码时,我刚开始还是试着使用MySQLdb模块的方式引用数据,结果发现报参数的错误 ,经查看代码发现 ,torndb在使用几个sql方法时较MySQLdb精简过了。具体各个方法的传参方法如下(注意参数个数):

close()
reconnect()
iter(query, *parameters, **kwparameters)
query(query, *parameters, **kwparameters)
get(query, *parameters, **kwparameters)
execute(query, *parameters, **kwparameters)
execute_lastrowid(query, *parameters, **kwparameters)
execute_rowcount(query, *parameters, **kwparameters)
executemany(query, parameters)
executemany_lastrowid(query, parameters)
executemany_rowcount(query, parameters)
update(query, *parameters, **kwparameters)
updatemany(query, parameters)
insert(query, *parameters, **kwparameters)
insertmany(query, parameters)
(0)

相关推荐

  • python的mysqldb安装步骤详解

    python的mysqldb安装步骤详解 安装MySQLdb: 一. 什么是MySQLdb? 解释:MySQLdb是Python操作MySQL的一个接口包.这里要理解一个概念,python操作数据库,都是需要一个类似MySQLdb这样的中间层,这些中间层抽象了具体的实现,提供了统一的API供开发者使用. 二. 如何安装MySQLdb? python2环境下: sudo pip install MySQL-python. MySQL-python目前暂时还不支持python3,有些小问题,可以安装

  • python中MySQLdb模块用法实例

    本文实例讲述了python中MySQLdb模块用法.分享给大家供大家参考.具体用法分析如下: MySQLdb其实有点像php或asp中连接数据库的一个模式了,只是MySQLdb是针对mysql连接了接口,我们可以在python中连接MySQLdb来实现数据的各种操作. python连接mysql的方案有oursql.PyMySQL. myconnpy.MySQL Connector 等,不过本篇要说的确是另外一个类库MySQLdb,MySQLdb 是用于Python链接Mysql数据库的接口,它

  • linux环境下python中MySQLdb模块的安装方法

    前言 最近开始学习python数据库编程后,在了解了基本概念,打算上手试验一下时,卡在了MYSQLdb包的安装上,折腾了半天才解决.记录一下我在linux中安装此包遇到的问题. 系统是ubuntn15.04. 1.下载 第一个问题是pycharm软件的模块安装功能Project Interpreter无法自动下载安装MYSQLdb包,显示 Error occurred when installling package 那没办法了,只好手动下载了.MYSQLdb包linux系统的下载的地址是:ht

  • 让python 3支持mysqldb的解决方法

    前言 在新的一年里祝大家前端都用ES6,php都用PHP7,Java都是JAVA9,python都是3.好了,下面进入本文的主要的内容,大家可能在python2.x中用习惯了mysqldb,但是在python3.x中已经不支持那个组件了.如果还想要让python 3支持mysqldb该怎么办呢?下面来一起看看吧. 原因 MySQLdb 只适用于python2.x,发现pip装不上.它在py3的替代品是: import pymysql pip install pymysql django+mysq

  • Windows下安装python MySQLdb遇到的问题及解决方法

    片头语:因为工作需要,在CentOS上搭建环境MySQL+Python+MySQLdb,个人比较习惯使用Windows系统的操作习惯,对纯字符的OS暂时还不太习惯,所以,希望能在Windows系统上也搭建一个类似的环境,用于开发.下面介绍的是在Windows环境下编译MySQLdb的过程.补充一句:最近在网上搜索到一个MySQLdb的Windows安装包,使用起来会更方便一些,地址:http://www.codegood.com/archives/4 或者到 http://www.jb51.ne

  • python MySQLdb Windows下安装教程及问题解决方法

    使用python访问mysql,需要一系列安装 linux下MySQLdb安装见  Python MySQLdb在Linux下的快速安装 http://www.jb51.net/article/65743.htm ------------------------------------------------------------- 以下是windows环境下的: 1. 安装数据库mysql 下载地址:http://www.mysql.com/downloads/ 可以顺带装个图形工具,我用的

  • Python中MySQLdb和torndb模块对MySQL的断连问题处理

    在使用python 对wordpress tag 进行细化代码处理时,遇到了调用MySQLdb模块时的出错,由于错误提示和问题原因相差甚远,查看了N久代码也未发现代码有问题.后来问了下师傅,被告知MySQLdb里有一个断接的坑 ,需要进行数据库重连解决. 一.报错代码及提示 运行出错的代码如下: import MySQLdb def getTerm(db,tag): cursor = db.cursor() query = "SELECT term_id FROM wp_terms where

  • Python中MYSQLdb出现乱码的解决方法

    本文实例讲述了Python中MYSQLdb出现乱码的解决方法,分享给大家供大家参考.具体方法如下: 一般来说,在使用mysql最麻烦的问题在于乱码. 查看mysql的编码: 命令:  复制代码 代码如下: show variables like 'character_set_%'; 可以看到如下结果: character_set_client为客户端编码方式: character_set_connection为建立连接使用的编码: character_set_database数据库的编码: ch

  • Python中的pandas表格模块、文件模块和数据库模块

    目录 一.Series数据结构 1.Series的创建 2.Series属性 2.Series缺失数据处理 二.DataFrame数据结构 1.DataFrame的创建 2.DataFrame属性 3.DataFrame取值 4.DataFrame值替换 5.处理丢失数据 6.合并数据 二.读取CSV文件 三.导入导出数据 1.读取文件导入数据 2.写入文件导出数据 3.实例 四.pandas读取json文件 五.pandas读取sql语句 pandas官方文档:https://pandas.p

  • Python中几种导入模块的方式总结

    模块内部封装了很多实用的功能,有时在模块外部调用就需要将其导入.常见的方式有如下几种: 1 . import >>> import sys >>> sys.path ['', 'C:\\Python34\\Lib\\idlelib', 'C:\\Windows\\system32\\python34.zip', 'C:\\Python34\\DLLs', 'C:\\Python34\\lib', 'C:\\Python34', 'C:\\Python34\\lib\\s

  • python中os和sys模块的区别与常用方法总结

    前言 本文主要介绍了关于python中os和sys模块区别与常用方法的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧. 官方解释: os: This module provides a portable way of using operating system dependent functionality. 翻译:提供一种方便的使用操作系统函数的方法. sys:This module provides access to some variables used or

  • 在Python中关于使用os模块遍历目录的实现方法

    一.Python中os模块的常见的使用方法 os.listdir(path):遍历path的文件或者文件夹,返回一个列表 os.path.join(path1,path2,--,pathn):拼接路径 os.path.isdir(path):判断此路径对应的是否是文件夹 os.path.isfile(path):判断是否是文件 os.path.dirname(path):返回路径的文件夹名 os.path.filename(path):返回路径的文件名 os.getcwd():获取当前路径 二.

  • 对python中的six.moves模块的下载函数urlretrieve详解

    实验环境:windows 7,anaconda 3(python 3.5),tensorflow(gpu/cpu) 函数介绍:所用函数为six.moves下的urllib中的函数,调用如下urllib.request.urlretrieve(url,[filepath,[recall_func,[data]]]).简单介绍一下,url是必填的指的是下载地址,filepath指的是保存的本地地址,recall_func指的是回调函数,下载过程中会调用可以用来显示下载进度. 实验代码:以下载cifa

  • Python中如何引入第三方模块

    Python中怎么使用第三方模块? 在Python可以在代码中导入模块,然后就可以使用第三方模块了. import 语句 想使用Python源文件,只需在另一个源文件里执行import语句,语法如下: import module1[, module2[,... moduleN] 当解释器遇到import语句,如果模块在当前的搜索路径就会被导入. 搜索路径是一个解释器会先进行搜索的所有目录的列表.如想要导入模块hello.py,需要把命令放在脚本的顶端: #!/usr/bin/python # -

  • Python中zipfile压缩文件模块的基本使用教程

    zipfile Python 中 zipfile 模块提供了对 zip 压缩文件的一系列操作. f=zipfile.ZipFile("test.zip",mode="") //解压是 r , 压缩是 w 追加压缩是 a mode的几种: 解压:r 压缩:w 追加压缩:a 压缩一个文件 创建一个压缩文件 test.zip(如果test.zip文件不存在) ,然后将 test.txt 文件加入到压缩文件 test.zip 中,如果原来的压缩文件中有内容,会清除原有的内容

随机推荐