如何更Pythonic连接MySQL数据库

概述

如果程序连数据库都没有,那么这个程序一般没什么大用处,在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中,我们不会显示调用commitrollback方法,而是通过上下文管理器来执行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

结束

你可能感兴趣的:(如何更Pythonic连接MySQL数据库)