概述
如果程序连数据库都没有,那么这个程序一般没什么大用处,在JAVA中,连接数据库用JDBC,但是在Python中,由于Python官方制定了操作数据库的标准,所以连接数据库非常简单。
连接数据库的步骤:
1)导入模块
2)使用connect函数连接数据库,并返回一个Connection对象
3)使用Connection对象的Cursor方法,返回一个Cursor对象
4)通过Cursor对象的execute方法执行SQL语句
5)如果执行的是查询语句,通过Cursor对象的fetchall获得结果
6)调用Cursor对象的close方法关闭Cursor
7)调用Connection对象的close方法关闭数据库连接
在Python中,有多个库可以访问MySQL数据库,比如说MySQLdb和PyMySQL。它们之间的使用方式是一样的,只在实现方式上有区别:MySQLdb是用C语言实现的,PyMySQL是用Python实现的。我们可以使用下面的方式尝试导入两个库:
try:
import MySQLdb as db
except ImportError:
import pymysql as db
我们先尝试导入MySQLdb,如果没有安装则尝试导入pymysql,如果都失败程序会退出。由于我们给他们起别名db
,之后的编码中就消除了差异。
下面,我们来具体看下如何连接数据库。
使用MySQLdb访问MySQL
首先根据官方的标准,来看看MySQLdb,了解下连接数据库相关的方法。
首先看看连接数据库的connect函数的一些参数:
- host: 数据库地址,默认通过socket访问本地数据库
- user: 登录数据库的用户名
- passwd: 登录数据库的密码
- db: 连接数据库后选择的库
- port : 连接的端口号
- unix_socket: socket的路径
- connect_timeout: 连接超时时间
- read_default_file: 读取MySQL配置文件中的配置进行连接
Connection对象的方法和异常:
使用connect方法连接数据库会返回一个Connection对象,Connection定义了很多方法和异常。其中,常用的有:
- begin: 开始事务
- commit:提交事务
- rollback:回滚事务
- cursor:返回一个Cursor对象
- autocommit:设置事务是否自动提交
实际编程中,一般不会直接调用begin,commit和rollback函数,而是通过上下文管理器来实现事务的提交和回滚操作。从源码中,我们可以知道为什么这么做:
class Connection(_mysql.connection):
def __enter__(self):
if self.get_autocommit():
self.query("BEGIN")
return self.cursor()
def __exit__(self, exc, value, tb):
if exc:
self.rollback()
else:
self.commit()
从源码中可以看到,调用Connection
类的__enter__
方法返回一个Cursor
对象,在一个Cursor
中执行的SQL语句组成一个事务,在这个事务执行过程中如果发生异常,则回滚整个事务,如果没有异常,则提交整个事务。所以,在Python中,我们不会显示调用commit
和rollback
方法,而是通过上下文管理器来执行SQL语句。
Cursor类的成员
Cursor对象表示数据库游标,用于执行SQL和获取SQL返回结果。常用的函数和常量如下所示:
- execute: 执行SQL语句
- close:关闭游标
- fetchall: 获取SQL语句所有记录
- fetchmany:获取SQL语句的多条记录
- fetchone:获取SQL语句的一条记录
- owncount: 常量,表示SQL语句的结果集返回了多少条记录
- arraysize:变量,保存了当前获取记录的下标
如何Pythonic连接数据库
下面让我们一步一步写出一个Pythonic读写数据库的例子,这个例子要做的是往一张表里插入若干记录,之后进行读取:
try:
import MySQLdb as db
except ImportError:
import pymysql as db
def create_table(conn):
sql_drop_table = "drop table if exists student"
sql_create_table = """
create table student(
sno int(11) not null,
sname varchar(255),
sage int(11),
primary key(sno)
)
"""
execute_sql(conn, sql_drop_table)
execute_sql(conn, sql_create_table)
def get_conn(**kwargs):
return db.connect(host=kwargs.get('host', 'localhost'),
user=kwargs.get('user'),
passwd=kwargs.get('passwd'),
port=kwargs.get('port', 3306),
db=kwargs.get('db'))
def execute_sql(conn, sql):
with conn as cur:
cur.execute(sql)
def insert_data(conn, sno, sname, sage):
INSERT_FORMAT = "insert into student value({0},'{1}',{2})"
sql = INSERT_FORMAT.format(sno, sname, sage)
execute_sql(conn, sql)
def main():
conn = get_conn(host="localhost",user="root",passwd="123456",db="test")
try:
create_table(conn)
insert_data(conn, 1,'a', 18)
with conn as cur:
cur.execute("select * from student")
rows = cur.fetchall()
for row in rows:
print(row)
print("success")
finally:
if conn:
conn.close()
main()
使用上下文管理器对数据库进行管理
在上面的代码中,为了保证数据库连接关闭,我们使用了try/finally
语句进行管理,但是看过Python上下文管理器解析的同学知道,这里其实是可以用with
语句代替的,而且是在函数级别上实现上下文管理器,所以我们可以用python标准库contextmanager
来实现,代码如下:
from contextlib import contextmanager
@contextmanager
def get_conn(**kwargs):
conn = db.connect(host=kwargs.get('host', 'localhost'),
user=kwargs.get('user'),
passwd=kwargs.get('passwd'),
port=kwargs.get('port', 3306),
db=kwargs.get('db'))
try:
yield conn
finally:
if conn:
conn.close()
这样对数据库连接进行封装之后,我们就可以直接用with
语句连接数据库,此时代码是这样写的:
conn_args = dict(host='127.0.0.1', user='test'...)
with get_conn(**conn_args):
with conn as cur:
cur.execute(SQL)
# other code
结束