代码改变世界

python MySQLdb安装和使用

2013-06-27 21:50  youxin  阅读(6472)  评论(0编辑  收藏  举报

MySQLdb是python的一个标准的连接和操纵mysql的模块。

下载地址;

https://pypi.python.org/pypi/MySQL-python/1.2.4#downloads

sourceforge地址:

http://sourceforge.net/projects/mysql-python/

说一下版本问题,去上面的网址可以看到,有2个版本MySQLdb1,MySQLdb2,默认下载的是MySqLdb2,可是到了第二版,作者又新开了一个项目叫moist

https://github.com/farcepest/moist

就是前面版本的升级,不知道作者为什么要新开一个项目。查看作者MySQLdb2的readme:

This is the legacy (1.x) version of MySQLdb. While it is still being maintained, there will not be a lot of new feature development.

TODO

  • A bugfix 1.2.4 release
  • A 1.3.0 release that will support Python 2.7-3.3

The 2.0 version is being renamed moist and lives at https://github.com/farcepest/moist

mysql python的说明文档:

http://sourceforge.net/p/mysql-python/mysqldb-2/ci/default/tree/doc/MySQLdb.txt

*************************

我用源代码编译安装时报错,于是直接下载exe文件安装就成功了。

通过pip安装

$pip install MySQL-python 

我最初使用这种形式安装的,不知道怎么回事,安装成功了,但导入包import MySQLdb总是说找不到。

安装完成,到你的python安装目录下的site-packages目录里检查以下文件是否存在,如果存在即代表安装成功了
Linux:MySQL_python-1.2.3c1-py2.6-linux-i686.egg
Mac OS X:MySQL_python-1.2.3c1-py2.6-macosx-10.4-x86_64.egg

 

import MysqlDB

报错:mysql mportError: DLL load failed: %1 不是有效的 Win32 应用程序

操作系统:win7 64位,安装mysqldb 后提示:ImportError DLL load failed: %1 不是有效的 Win32 应用程序,是由于安装的32位的 MySql-python-1.2.3.win32-py2.exe,,只要改成64位版本的就可以了。

 

怎么看安装的模块是多少位?

MySQL-python-1.2.3.win-amd64-py2.7.exe

MySQL-python-1.2.5.win32-py2.7.exe

介个就很明显了。

在官网:http://sourceforge.net/projects/mysql-python/ 没有64的提供。

 

经过搜索,下载到了

MySQL-python-1.2.5.win-amd64-py2.7.exe

 

 

参考之前的文章:

Python ImportError: DLL load failed: %1 不是有效的 Win32 应用程序。

 

 

select:

import MySQLdb
conn = MySQLdb.connect(host='127.0.0.1', port=3306,user='root', passwd='longforfreedom',db='python')
cursor = conn.cursor()
count = cursor.execute('select * from test')
print '总共有 %s 条记录',count
#获取一条记录,每条记录做为一个元组返回
print "只获取一条记录:"
result = cursor.fetchone();
print result
#print 'ID: %s info: %s' % (result[0],result[1])
print 'ID: %s info: %s' % result
#获取5条记录,注意由于之前执行有了fetchone(),所以游标已经指到第二条记录了,也就是从第二条开始的所有记录
print "只获取5条记录:"
results = cursor.fetchmany(5)
for r in results:
print r
print "获取所有结果:"
#重置游标位置,0,为偏移量,mode=absolute | relative,默认为relative,
cursor.scroll(0,mode='absolute')
#获取所有结果
results = cursor.fetchall()
for r in results:
print r
conn.close()

最开始我连接不上:报错

_mysql_exceptions.OperationalError: (2003, "Can't connect to MySQL server on 'localhost' (10061)")

conn = MySQLdb.connect(host='localhost', port=3306,user='root', passwd='longforfreedom',db='python')

import MySQLdb
try:
    conn=MySQLdb.connect(host='127.0.0.1',user='root',passwd='admin',db='mysql',port=3306)
    cur=conn.cursor()
    #cur.execute('select * from user')
    cur.execute('select version()')
    data = cur.fetchone()
    print "Databases version: %s " %  data
    cur.close()
    conn.close()
except MySQLdb.Error,e:
     print "Mysql Error %d: %s" % (e.args[0], e.args[1])

 

 

把loclhoast改为ip地址就可以了。具体原因不清楚。

创建数据库:

import MySQLdb
#建立和数据库系统的连接
conn = MySQLdb.connect(host='localhost', user='root',passwd='longforfreedom')
#获取操作游标
cursor = conn.cursor()
#执行SQL,创建一个数据库.
cursor.execute("""create database python """)
#关闭连接,释放资源
cursor.close();

创建数据库,创建表,插入数据,插入多条数据

import MySQLdb
#建立和数据库系统的连接
conn = MySQLdb.connect(host='localhost', user='root',passwd='longforfreedom')
#获取操作游标
cursor = conn.cursor()
#执行SQL,创建一个数据库.
cursor.execute("""create database if not exists python""")
#选择数据库
conn.select_db('python');
#执行SQL,创建一个数据表.
cursor.execute("""create table test(id int, info varchar(100)) """)
value = [1,"inserted ?"];
#插入一条记录
cursor.execute("insert into test values(%s,%s)",value);
values=[]
#生成插入参数值
for i in range(20):
values.append((i,'Hello mysqldb, I am recoder ' + str(i)))
#插入多条记录
cursor.executemany("""insert into test values(%s,%s) """,values);
#关闭连接,释放资源
cursor.close();

我现在插入有点问题,插入不了。

摘自doc上的话:

To perform a query, you first need a cursor, and then you can execute
queries on it::
 
c=db.cursor()
max_price=5
c.execute("""SELECT spam, eggs, sausage FROM breakfast
WHERE price < %s""", (max_price,)) 注意,后面一个参数为tuple
 
In this example, ``max_price=5`` Why, then, use ``%s`` in the
string? Because MySQLdb will convert it to a SQL literal value, which
is the string '5'. When it's finished, the query will actually say,
"...WHERE price < 5".
 
Why the tuple? Because the DB API requires you to pass in any
parameters as a sequence. Due to the design of the parser, (max_price)
is interpreted as using algebraic grouping and simply as max_price and
not a tuple. Adding a comma, i.e. (max_price,) forces it to make a
tuple.
 
And now, the results::
 
>>> c.fetchone()
(3L, 2L, 0L)
 
Quite unlike the ``_mysql`` example, this returns a single tuple,
which is the row, and the values are properly converted by default...
except... What's with the L's?
 为什么后面有L,long integers?
As mentioned earlier, while MySQL's INTEGER column translates
perfectly into a Python integer, UNSIGNED INTEGER could overflow, so
these values are converted to Python long integers instead.
 
If you wanted more rows, you could use ``c.fetchmany(n)`` or
``c.fetchall()``. These do exactly what you think they do. On
``c.fetchmany(n)``, the ``n`` is optional and defaults to
``c.arraysize``, which is normally 1. Both of these methods return a
sequence of rows, or an empty sequence if there are no more rows. If
you use a weird cursor class, the rows themselves might not be tuples.
 
Note that in contrast to the above, ``c.fetchone()`` returns ``None``
when there are no more rows to fetch.
 
The only other method you are very likely to use is when you have to
do a multi-row insert::
 
c.executemany(
"""INSERT INTO breakfast (name, spam, eggs, sausage, price)
VALUES (%s, %s, %s, %s, %s)""",
[
("Spam and Sausage Lover's Plate", 5, 1, 8, 7.95 ),
("Not So Much Spam Plate", 3, 2, 0, 3.95 ),
("Don't Wany ANY SPAM! Plate", 0, 4, 3, 5.95 )
] )
 
Here we are inserting three rows of five values. Notice that there is
a mix of types (strings, ints, floats) though we still only use
``%s``. And also note that we only included format strings for one
row. MySQLdb picks those out and duplicates them for each row.
 
其实 还可以这么写:
value=('单人间',1,5)
cursor.execute("insert into room (roomType,hotelId,roomNum) values(%s,%s,%s)",value)
利用python百分号的威力,可以写成:

value1='单人间'
value2=5
value3=5

cursor.execute("insert into room (roomType,hotelId,roomNum) values('%s',%d,%d)" % (value1,value2,value3) )

insertId=conn.insert_id()
affectedRows=conn.affected_rows()
conn.commit()

 这里主要利用%后面的会替换前面的占位符。
上面的输出:

14 insert id
1 affected rows。

这是2个很重要的方法。

 

一直困扰我的问题:下面的代码:
import MySQLdb

def dbinsert():
    conn=MySQLdb.connect(host='127.0.0.1',port=3306,user='root',passwd='sm159357',db='hotelbookown')

    cursor = conn.cursor()
    cursor.execute("select * from user")
    results=cursor.fetchall()
    for r in results:
        print r
    value=('user12','user12')
    #插入一条记录
    cursor.execute("insert into user (username,password) values(%s,%s)",value)
     

我确实 可以运行,也不报错,但是数据库就是没有插入记录,很郁闷。在网上看到帖子说要在execute后加个

conn.commit()就可以了,果不其然,确实可以。

 

解决中午插入乱码

在文件前面加coding=utf-8

连接时:

conn=MySQLdb.connect(host='127.0.0.1',port=3306,user='root',passwd='sm159357',db='hotelbookown',charset='utf8')

中文插入时应该是这样

a=u'中文

如果是a=’中文‘则错误。

 

插入多条数据(带有int型的)都用%s 会自动转换的。

 valueArr=[
        ('单人间',1,5),
        ('单人间',2,5),
        ('双人间',3,5)
        ]
    cursor.executemany("insert into room (roomType,hotelId,roomNum) values(%s,%s,%s)",valueArr)
    conn.commit()

关闭方法,

cursor.close()

conn.close()

 

 

很奇怪我为什么delet无效,原因在于没有用

 conn.commit()


测试增删改查操作
import MySQLdb

conn = MySQLdb.connect(
                       host = '127.0.0.1',
                       port = 3306,
                       user = 'root',
                       passwd = '142857',
                       db = 'user',
                       charset = 'utf8'
                       )

cursor = conn.cursor()
sql_insert = 'insert into user_table(`id`,`name`) values(10,"name10")'
sql_update = 'update user_table set `name`="name_07" where id =7'
sql_delete = "delete from user_table where id<3 "


try:
    cursor.execute(sql_insert)
    print cursor.rowcount
    
    cursor.execute(sql_update)
    print cursor.rowcount
    
    cursor.execute(sql_delete)
    print cursor.rowcount
    
    conn.commit()
except Exception as e:
    print e
    conn.rollback()

cursor.close()
conn.close()

这里特别要注意的是sql语句使用execute()方法执行后,要使用commit()方法提交处理,当事务失败后,要调用rollback()方法进行事务的回滚。注意尽量避免使用不支持事务的存储引擎。

使用python操作数据库模拟银行转账的功能

 

import sys
import MySQLdb

class TransferMoney():
    def __init__(self,conn):
        self.conn = conn
    

    def check_acct_available(self, acctid):
        cursor = self.conn.cursor()
        try:
            sql = 'select * from account where acctid=%s' % acctid
            cursor.execute(sql)
            print 'check_acct_available:' + sql
            rs = cursor.fetchall()
            if len(rs) != 1:
                raise Exception("账号%s不存在" % acctid)
        finally:
            cursor.close()
    
    def has_enough_money(self, acctid, money):
        cursor = self.conn.cursor()
        try:
            sql = 'select * from account where acctid=%s and money > %s' % (acctid,money)
            cursor.execute(sql)
            print 'has_enough_money:' + sql
            rs = cursor.fetchall()
            if len(rs) != 1:
                raise Exception("账号%s没有足够的钱" % acctid)
        finally:
            cursor.close()
    
    
    def reduce_money(self, acctid, money):
        cursor = self.conn.cursor()
        try:
            sql = 'update account set money=money-%s where acctid=%s' % (money,acctid)
            cursor.execute(sql)
            print 'reduce_money:' + sql
            if cursor.rowcount != 1:
                raise Exception("账号%s减款失败" % acctid)
        finally:
            cursor.close()
    
    
    def add_money(self, acctid, money):
        cursor = self.conn.cursor()
        try:
            sql = 'update account set money=money+%s where acctid=%s' % (money,acctid)
            cursor.execute(sql)
            print 'add_money:' + sql
            if cursor.rowcount != 1:
                raise Exception("账号%s加款失败" % acctid)
        finally:
            cursor.close()
    
    
    def transfer(self,source_acctid,target_acctid,money):
        try:
            self.check_acct_available(source_acctid)
            self.check_acct_available(target_acctid)
            self.has_enough_money(source_acctid,money)
            self.reduce_money(source_acctid,money)
            self.add_money(target_acctid,money)
            self.conn.commit()
        except Exception as e:
            self.conn.rollback()
            raise e
        
        
if __name__ == "__main__":
    source_acctid = sys.argv[1]
    target_acctid = sys.argv[2]
    money = sys.argv[3]
    print source_acctid,' ',target_acctid,' ',money
    conn = MySQLdb.connect(host='127.0.0.1',port = 3306,user = 'root',passwd='142857',db ='user',charset = 'utf8')
    tr_money = TransferMoney(conn)
    try:
        tr_money.transfer(source_acctid,target_acctid,money)
    except Exception as e:
        print u'出现问题',e
    finally:
        conn.close()  
View Code

账户 11 余额为110元

账户 12 余额为10元

执行12 11 100意为账户12转给账户11 100元,则转账失败

 

转账失败那么11的钱没增加,12的钱也不能少,回到数据的初始状态,这就是事务的回滚。

当账户11转给12账户100元时,可以完成操作,转账成功。回到数据库刷新可以看到11的钱少了100元,12的钱增加了100元。

 

 

参考:http://blog.sina.com.cn/s/blog_7cc54c730101hal3.html

 

保证输出没有乱码:

  我用了下面几个措施,保证MySQL的输出没有乱麻:
   1 Python文件设置编码 utf-8 (文件前面加上 #encoding=utf-8)
   2 MySQL数据库charset=utf-8
   3 Python连接MySQL是加上参数 charset=utf8
   4 设置Python的默认编码为 utf-8 (sys.setdefaultencoding(utf-8)
  mysql_test.py  

#encoding=utf-8
  import sys
  import MySQLdb
  
  reload(sys)
  sys.setdefaultencoding('utf-8')
  
  db=MySQLdb.connect(user='root',charset='utf8')
  cur=db.cursor()
  cur.execute('use mydb')
  cur.execute('select * from mytb limit 100')
  
  f=file("/home/user/work/tem.txt",'w')
  
  for i in cur.fetchall():
   f.write(str(i))
   f.write(" ")
  
  f.close()
  cur.close()

上面是linux上的脚本,windows下运行正常!
  
  注:MySQL的配置文件设置也必须配置成utf8
  
  设置 MySQL 的 my.cnf 文件,在 [client]/[mysqld]部分都设置默认的字符集(通常在/etc/mysql/my.cnf):
  [client]
  default-character-set = utf8
  [mysqld]
  default-character-set = utf8

 

 

 
参考:
http://blog.chinaunix.net/uid-8487640-id-3183185.html
http://www.iteye.com/topic/573092
http://hi.baidu.com/onekunp/item/80771e3fd63905be124b1440
http://www.linuxidc.com/Linux/2012-05/60353.htm

 

遇到的问题:

self.cursor=self.cursor.execute("select id from urllist where url='%s' " % url )
res=self.cursor.fetchone()

错误:

AttributeError: 'long' object has no attribute 'fetchone'

其实,execute select id 返回的是类似(1L,)这样的元祖。

为什么上面错误,因为execute返回的select的数目count,

不用赋值。应该是这样:

self.cursor.execute("select id from urllist where url='%s' " % url )
res=self.cursor.fetchone()

 

 

centos安装pythondb

 

步骤如下:

#安装MySQLdb
wget https://pypi.python.org/packages/source/M/MySQL-python/MySQL-python-1.2.5.zip#md5=654f75b302db6ed8dc5a898c625e030c
unzip MySQL-python-1.2.5.zip
cd MySQL-python-1.2.5
chmod -R 775 *
python setup.py build

python setup.py install

 

 

mysql-python安装时EnvironmentError: mysql_config not found

就是要找到mysql_config这个可执行文件

只要原因是没有安装:libmysqlclient-dev

sudo apt-get install libmysqlclient-dev

找到mysql_config文件的路径

sudo updatedb
locate mysql_config

mysql_config的位置为:/usr/bin/mysql_config

在mysql-python源码包下找到:setup_posix.py 文件,然后找到文件中的 mysql_config.path 将其值改为:/usr/bin/mysql_config,然后 sudo python setup.py install ,就ok了

 

_LINUX -DUNIV_LINUX
_mysql.c:29:20: fatal error: Python.h: No such file or directory
#include "Python.h"
^

安装:

 yum install python-devel .