eventlet的db_pool文檔地址:http://eventlet.net/doc/modules/db_pool.html
需要先安裝pymysql 0.9.3模塊和eventlet 0.25.1模塊。具體代碼如下:
import pymysql
from eventlet.db_pool import RawConnectionPool, ConnectionPool, DatabaseConnector
# 一種簡單的數據庫連接池
pool = RawConnectionPool(pymysql, min_size=0, max_size=4, max_idle=10, max_age=30, connect_timeout=5,
host='masaike.mysql.rds.aliyuncs.com',
port=3306,
user='mysqlsa',
password='123456',
db='call_center_robot')
is_dev = False
if is_dev:
con_pool = ConnectionPool(pymysql,
host='masaike.mysql.rds.aliyuncs.com',
port=3306,
user='call_center_sql',
password='123456',
db='call_center_robot')
else:
# 直接創建數據庫連接池
con_pool = ConnectionPool(pymysql,
host='masaike.mysql.rds.aliyuncs.com',
port=3306,
user='mysqlsa',
password='123456',
db='call_center_robot')
def search_sql(total_sql):
'''
單庫查詢
連接數據庫,執行sql查詢
:param total_sql:
'''
# 從連接池拿連接對象
with con_pool.item() as db:
try:
with db.cursor(pymysql.cursors.DictCursor) as cursor:
# 使⽤execute⽅法執⾏SQL語句
cursor.execute(total_sql)
# 獲取數據
data = cursor.fetchall()
db.commit()
except:
data = ''
# 把連接放回連接池
con_pool.put(db)
return data
# 多個主機的數據庫信息
db_info = {
# 連接池名稱(原文檔這裏是數據庫host)
'test': {
'port': 3306, # 端口
'user': 'mysqlsa', # 用戶名
'host': 'masaike.test.mysql.rds.aliyuncs.com', # 主機名
'password': '123456', # 密碼
'db': 'call_center_robot' # 數據庫名
},
'prod': {
'port': 3306,
'host': 'masaike.prod.mysql.rds.aliyuncs.com',
'user': 'call_center_sql',
'password': '123456',
'db': 'call_center_robot'
},
}
# 創建數據庫連接池池
db_pool = DatabaseConnector(pymysql, db_info)
def search_sql_pool(total_sql, pool_name='deault', db_name=''):
'''
多庫查詢
:param total_sql: 被執行的sql
:param pool_name: 連接池名稱
:param db_name: 數據庫名
:return:
'''
# 從數據庫連接池池中獲取連接池
conn_pool = db_pool.get(pool_name, db_name)
with conn_pool.item() as db:
try:
with db.cursor(pymysql.cursors.DictCursor) as cursor:
# 使⽤execute⽅法執⾏SQL語句
cursor.execute(total_sql)
# 獲取數據
data = cursor.fetchall()
# 提交
db.commit()
except:
data = ''
# 把連接放回連接池
conn_pool.put(db)
return data
if __name__ == '__main__':
data = search_sql('select now()')
print(data)
data = search_sql_pool('select now()', 'test', 'call_center_robot')
print(data)
說明:對於上面代碼裏的多個主機數據庫信息字典有一點說明,在原文檔使用host作爲字典的key,看一下文檔。
但是一般數據庫主機的host都很長,作爲參數傳遞不方便。 查看了eventlet.db_pool的DatabaseConnector源碼,發現源碼有一處問題,也可能是作者故意設置的。
class DatabaseConnector(object):
"""
This is an object which will maintain a collection of database
connection pools on a per-host basis.
"""
def __init__(self, module, credentials,
conn_pool=None, *args, **kwargs):
"""constructor
*module*
Database module to use.
*credentials*
Mapping of hostname to connect arguments (e.g. username and password)
"""
assert(module)
self._conn_pool_class = conn_pool
if self._conn_pool_class is None:
self._conn_pool_class = ConnectionPool
self._module = module
self._args = args
self._kwargs = kwargs
# this is a map of hostname to username/password
self._credentials = credentials
self._databases = {}
def credentials_for(self, host):
if host in self._credentials:
return self._credentials[host]
else:
return self._credentials.get('default', None)
def get(self, host, dbname):
"""Returns a ConnectionPool to the target host and schema.
"""
key = (host, dbname)
if key not in self._databases:
new_kwargs = self._kwargs.copy()
new_kwargs['db'] = dbname
new_kwargs['host'] = host
new_kwargs.update(self.credentials_for(host))
dbpool = self._conn_pool_class(
self._module, *self._args, **new_kwargs)
self._databases[key] = dbpool
return self._databases[key]
DatabaseConnector的get方法裏,如果key對應的連接池不存在,則會創建一個新的連接池,credentials_for方法會根據host返回數據庫信息,最後用credentials_for返回的數據庫信息更新當前的new_kwargs。所以如果把db_info字典的key改成連接池名稱,把host放到連接池名稱對應的字典中,真正的host會把當前new_kwargs裏的host(連接池名稱)更新了,如果這是這個模塊作者故意做的,不得不感嘆大佬的編程藝術~~