SQLAlchemy初始化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
from sqlalchemy import create_enginefrom sqlalchemy.orm import sessionmakerfrom sqlalchemy import Columnfrom sqlalchemy.types import String, Integerfrom sqlalchemy.ext.declarative import declarative_baseengine = create_engine('postgresql://test@localhost:5432/test' ) DBSession = sessionmaker(engine) session = DBSession() BaseModel = declarative_base() class User (BaseModel) : __tablename__ = 'user' id = Column(String, primary_key=True ) username = Column(String, index=True ) class Session (BaseModel) : __tablename__ = 'session' id = Column(String, primary_key=True ) user = Column(String, index=True ) ip = Column(String) query = session.query(Session, User.username).join(User, User.id == Session.user) for i in query: print dir(i)
SQLAlchemy创建连接
Engine
engine 的定义包含了三部分的内容:
具体数据库类型的实现 连接池 策略(即engine自己的实现)
所谓的数据库类型即是MYSQL
, Postgresql
, SQLite
这些不同的数据库. 一般创建 engine 是使用create_engine
方法:
1
engine = create_engine('postgresql+psycopg2://scott:tiger@localhost/mydatabase' )
对于这个字符串, SQLAlchemy 提供了工具可用于处理它:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
from sqlalchemy import create_enginefrom sqlalchemy.engine.url import make_urlfrom sqlalchemy.engine.url import URLs = 'postgresql://test@localhost:5432/bbcustom' url = make_url(s) s = URL(drivername='postgresql' , username='test' , password="" ,host="localhost" , port=5432 , database="bbcustom" ) engine = create_engine(url) engine = create_engine(s) print engine.execute('select id from "user"' ).fetchall()
create_engine
函数有很多的控制参数, 这个后面再详细说.
Engine的策略
create_engine
的调用, 实际上会变成strategy.create
的调用. 而strategy
就是engine
的实现细节. strategy
可以在create_engine
调用时通过strategy
参数指定, 目前官方的支持有三种:
plain, 默认的 threadlocal, 连接是线程局部的 mock, 所有的 SQL 语句的执行会使用指定的函数
mock
这个实现, 会把所有的 SQL
语句的执行交给指定的函数来做, 这个函数是由create_engine
的 executor
参数指定:
1 2 3 4 5 6 7
def f (sql, *args, **kargs) : print sql, args, kargs s = 'postgresql://test@localhost:5432/bbcustom' engine = create_engine(s, strategy='mock' , executor=f) print engine.execute('select id from "user"' )
各数据库实现
各数据库的实现在 SQLAlchemy 中分成了两个部分, 一是数据库的类型, 二是具体数据库中适配的客户端实现. 比如对于 Postgresql 的访问, 可以使用psycopg2
, 也可以使用pg8000
:
1 2 3
s = 'postgresql+psycopg2://test@localhost:5432/bbcustom' s = 'postgresql+pg8000://test@localhost:5432/bbcustom' engine = create_engine(s)
具体的适配工作, 是需要在代码中实现一个 Dialect 类来完成的. 官方的实现在 dialects 目录下.
获取具体的 Dialect 的行为, 则是前面提到的URL
对象的get_dialect
方法.create_engine
时你单传一个字符串,SQLAlchemy
自己也会使用make_url
得到一个URL
的实例).
连接池
SQLAlchemy 支持连接池, 在create_engine
时添加相关参数即可使用.
pool_size:连接数 max_overflow:最多多几个连接 pool_recycle:连接重置周期 pool_timeout:连接超时时间
连接池效果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
from sqlalchemy import create_enginefrom sqlalchemy.engine.url import make_urlfrom sqlalchemy.engine.url import URLs = 'postgresql://test@localhost:5432/bbcustom' engine = create_engine(s, pool_size=2 , max_overflow=0 ) from threading import Threaddef f () : print engine.execute('select pg_sleep(5)' ).fetchall() p = [] for i in range(3 ): p.append(Thread(target=f)) for t in p: t.start()
连接池的实现, 在create_engine
调用时也可以指定:
1 2
from sqlalchemy.pool import QueuePoolengine = create_engine('sqlite:///file.db' , poolclass=QueuePool)
还有:
1 2 3 4
from sqlalchemy.pool import NullPoolengine = create_engine( 'postgresql+psycopg2://scott:tiger@localhost/test' , poolclass=NullPool)
或者仅仅是获取连接的方法:
1 2 3 4 5 6 7 8 9
import sqlalchemy.pool as poolimport psycopg2def getconn () : c = psycopg2.connect(username='ed' , host='127.0.0.1' , dbname='test' ) return c engine = create_engine('postgresql+psycopg2://' , creator=getconn)
连接池可以被单独使用:
1 2 3 4 5 6 7 8 9 10 11 12
import sqlalchemy.pool as poolimport psycopg2def getconn () : c = psycopg2.connect(username='ed' , host='127.0.0.1' , dbname='test' ) return c mypool = pool.QueuePool(getconn, max_overflow=10 , pool_size=5 ) conn = mypool.connect() cursor = conn.cursor() cursor.execute("select foo" )
连接池可以被多个 engine 共享使用:
1
e = create_engine('postgresql://' , pool=mypool)