参悟python元类(又称metaclass)系列实战(四)
写在前面
在上一章节参悟python元类(又称metaclass)系列实战(三)完成了
users类
和users表
的字段映射;
在继续丰富users类
的操作之前, 我们花一章来完成mysql的链接;
有误的地方恳请大神指正下。
创建全局连接池, 以求避免频繁地打开和关闭数据库连接
-
因为查询耗时, 计划引入异步, 即
async/await
(不懂没关系, 就当是普通代码, 只是调用方式特别而已)$ pip3 install aiomysql # 通过pip安装
-
创建
Mysql类
, 定义静态方法createPool
import aiomysql class Mysql: @staticmethod async def createPool(): '''连接池由全局变量__pool存储,缺省情况下将编码设置为utf8,自动提交事务''' try: global __pool __pool = await aiomysql.create_pool( host='localhost', # mysql服务器地址 port=3306, # mysql监听端口 user='root', # mysql用户名 password='passwd', # mysql密码 db='ormdemo', # mysql实例名(database) charset='utf8', # 编码设置 autocommit=True, # 自动提交insert/update/delete maxsize=10, # 连接池上限 minsize=1 # 连接池下限 ) print('创建成功') except Exception as e: print(f'连接 mysql 出错:{e}') # 测试代码 if __name__ == '__main__': import asyncio loop = asyncio.get_event_loop() loop.run_until_complete(Mysql.createPool())
-
给
Mysql类
新增静态方法select
、execute
@staticmethod async def select(sql, args, size=None): '''传入SQL语句和SQL参数 @sql : sql语句 @args: 条件值列表 @size: 查询的结果集大小 ''' print(f'{sql} ==> {args}') # 使用with上下文管理器, 自动执行close async with __pool.acquire() as conn: # acquire: 从空闲池获得连接。如果需要,并且池的大小小于maxsize,则创建新连接。 async with conn.cursor(aiomysql.DictCursor) as cur: # cursor: 连接的游标 # DictCursor: 作为字典返回结果的游标 await cur.execute(sql.replace('?', '%s'), args or ()) # sql.replace('?', '%s'): 'SELECT * FROM users WHERE uid=?'.replace('?', '%s') # args or (): 'SELECT * FROM users WHERE uid=%s' % (101,) if size: rs = await cur.fetchmany(size) else: rs = await cur.fetchall() print(f'rows returned: {len(rs)}') return rs @staticmethod async def execute(sql, args, autocommit=True): ''' INSERT、UPDATE、DELETE操作,可以通用的execute函数, 因为这3种SQL的执行都需要相同的参数, 返回一个整数表示影响的行数 ''' print(f'{sql} ==> {args}') async with __pool.acquire() as conn: if not autocommit: await conn.begin() # 开始处理 try: async with conn.cursor(aiomysql.DictCursor) as cur: await cur.execute(sql.replace('?', '%s'), args) affected = cur.rowcount # 受影响的行数 if not autocommit: await conn.commit() # 提交更改, 非自动提交时才需要 except Exception as e: if not autocommit: await conn.rollback() # 回滚更改 raise Exception(e) return affected
测试下select
if __name__ == '__main__':
import asyncio
loop = asyncio.get_event_loop()
loop.run_until_complete(Mysql.createPool())
rs = loop.run_until_complete(Mysql.select('select uid, name from users where uid=?', [101]))
print(rs)
- 控制台输出
创建成功
select * from users where uid=? ==> [101]
rows returned: 1
[{'uid': 101, 'name': 'z417'}]
总结
-
定义了
Mysql类
, 其中有3个静态方法 -
引入了异步, 调用方式共分两步