如何更Pythonic连接MySQL数据库

作者: 一根薯条 | 来源:发表于2018-03-22 18:44 被阅读0次

    概述

    如果程序连数据库都没有,那么这个程序一般没什么大用处,在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数据库

        本文链接:https://www.haomeiwen.com/subject/dqtzqftx.html