sqlalchemy源代码阅读随笔(2)
这次阅读的,是Strategies.py文件。
文件自身,是这么描述的:
"""Strategies for creating new instances of Engine types. These are semi-private implementation classes which provide the
underlying behavior for the "strategy" keyword argument available on
:func:`~sqlalchemy.engine.create_engine`. Current available options are
``plain``, ``threadlocal``, and ``mock``. New strategies can be added via new ``EngineStrategy`` classes.
"""
首先,定义了一个基础类(也可以认为是抽象类):
class EngineStrategy(object):
"""An adaptor that processes input arguments and produces an Engine. Provides a ``create`` method that receives input arguments and
produces an instance of base.Engine or a subclass. """ def __init__(self):
strategies[self.name] = self def create(self, *args, **kwargs):
"""Given arguments, returns a new Engine instance.""" raise NotImplementedError()
这里我们注意到,定义了create方法,要求后续的继承类必须实现。而self.name却是没有定义的。
而:
strategies[self.name] = self,
是把自己这个class传入到strategies变量中。
进一步看他的继承类:
class DefaultEngineStrategy(EngineStrategy):
"""Base class for built-in strategies.""" def create(self, name_or_url, **kwargs):
# create url.URL object
u = url.make_url(name_or_url) plugins = u._instantiate_plugins(kwargs) u.query.pop('plugin', None) entrypoint = u._get_entrypoint()
dialect_cls = entrypoint.get_dialect_cls(u) if kwargs.pop('_coerce_config', False):
def pop_kwarg(key, default=None):
value = kwargs.pop(key, default)
if key in dialect_cls.engine_config_types:
value = dialect_cls.engine_config_types[key](value)
return value
else:
pop_kwarg = kwargs.pop dialect_args = {}
# consume dialect arguments from kwargs
for k in util.get_cls_kwargs(dialect_cls):
if k in kwargs:
dialect_args[k] = pop_kwarg(k) dbapi = kwargs.pop('module', None)
if dbapi is None:
dbapi_args = {}
for k in util.get_func_kwargs(dialect_cls.dbapi):
if k in kwargs:
dbapi_args[k] = pop_kwarg(k)
dbapi = dialect_cls.dbapi(**dbapi_args) dialect_args['dbapi'] = dbapi for plugin in plugins:
plugin.handle_dialect_kwargs(dialect_cls, dialect_args) # create dialect
dialect = dialect_cls(**dialect_args) # assemble connection arguments
(cargs, cparams) = dialect.create_connect_args(u)
cparams.update(pop_kwarg('connect_args', {}))
cargs = list(cargs) # allow mutability # look for existing pool or create
pool = pop_kwarg('pool', None)
if pool is None:
def connect(connection_record=None):
if dialect._has_events:
for fn in dialect.dispatch.do_connect:
connection = fn(
dialect, connection_record, cargs, cparams)
if connection is not None:
return connection
return dialect.connect(*cargs, **cparams) creator = pop_kwarg('creator', connect) poolclass = pop_kwarg('poolclass', None)
if poolclass is None:
poolclass = dialect_cls.get_pool_class(u)
pool_args = {
'dialect': dialect
} # consume pool arguments from kwargs, translating a few of
# the arguments
translate = {'logging_name': 'pool_logging_name',
'echo': 'echo_pool',
'timeout': 'pool_timeout',
'recycle': 'pool_recycle',
'events': 'pool_events',
'use_threadlocal': 'pool_threadlocal',
'reset_on_return': 'pool_reset_on_return',
'pre_ping': 'pool_pre_ping'}
for k in util.get_cls_kwargs(poolclass):
tk = translate.get(k, k)
if tk in kwargs:
pool_args[k] = pop_kwarg(tk) for plugin in plugins:
plugin.handle_pool_kwargs(poolclass, pool_args) pool = poolclass(creator, **pool_args)
else:
if isinstance(pool, poollib._DBProxy):
pool = pool.get_pool(*cargs, **cparams)
else:
pool = pool pool._dialect = dialect # create engine.
engineclass = self.engine_cls
engine_args = {}
for k in util.get_cls_kwargs(engineclass):
if k in kwargs:
engine_args[k] = pop_kwarg(k) _initialize = kwargs.pop('_initialize', True) # all kwargs should be consumed
if kwargs:
raise TypeError(
"Invalid argument(s) %s sent to create_engine(), "
"using configuration %s/%s/%s. Please check that the "
"keyword arguments are appropriate for this combination "
"of components." % (','.join("'%s'" % k for k in kwargs),
dialect.__class__.__name__,
pool.__class__.__name__,
engineclass.__name__)) engine = engineclass(pool, dialect, u, **engine_args) if _initialize:
do_on_connect = dialect.on_connect()
if do_on_connect:
def on_connect(dbapi_connection, connection_record):
conn = getattr(
dbapi_connection, '_sqla_unwrap', dbapi_connection)
if conn is None:
return
do_on_connect(conn) event.listen(pool, 'first_connect', on_connect)
event.listen(pool, 'connect', on_connect) def first_connect(dbapi_connection, connection_record):
c = base.Connection(engine, connection=dbapi_connection,
_has_events=False)
c._execution_options = util.immutabledict()
dialect.initialize(c)
event.listen(pool, 'first_connect', first_connect, once=True) dialect_cls.engine_created(engine)
if entrypoint is not dialect_cls:
entrypoint.engine_created(engine) for plugin in plugins:
plugin.engine_created(engine) return engine
只是实现了create,但是,还是没有name,再往下看:
class PlainEngineStrategy(DefaultEngineStrategy):
"""Strategy for configuring a regular Engine.""" name = 'plain'
engine_cls = base.Engine
在这里,才给name赋值了。
意味着,之前的两个class,都不适合外部调用。
线面,我们看看create_engine的过程,通过pycharm的单步调试去看:
from sqlalchemy.engine import base, threadlocal, url,create_engine engineurl ='mysql+pymysql://root:root@192.168.31.196:3306/story_line_dev?charset=utf8'
storyengine = create_engine(engineurl, max_overflow=5,echo=True)
create_engine是在engine包里(从源代码结构看,是engine目录下),对于package来说,首先调用的是__init__.py文件:
default_strategy = 'plain'
strategy = kwargs.pop('strategy', default_strategy)
strategy = strategies.strategies[strategy]
return strategy.create(*args, **kwargs)
关键是第三行代码:
strategy = strategies.strategies[strategy],这里实际上就是:
strategy = strategies.strategies[‘plain’]
这里又要插一句,在import的时候,就执行了这个代码:
strategies.py文件里的:PlainEngineStrategy() 因为,在import的时候,类和方法的名称被import,但不执行。模块里的直接的方法(比如上面写的),会执行。 下面,我们看看:PlainEngineStrategy做了啥:
name = 'plain'
engine_cls = base.Engine 这里,就是调用了base.Engine 关于base,下一次再说。
sqlalchemy源代码阅读随笔(2)的更多相关文章
- sqlalchemy源代码阅读随笔(1)
今天看的,是url.py模块,这个在create_engine中,起到的最用很大,其本质,就是对访问数据库的url,进行操作管里.我们可以直接访问这个类. 看一个简单的代码: from sqlalch ...
- sqlalchemy源代码阅读随笔(4):url。py 阅读
在_to_string中,有 _rfc_1738_quote(text): 这个函数.这个主要是遵循 RFC 1738的规则.对传入的信息(主要是用户名或者密码)进行格式匹配.其代码就一行: retu ...
- 《UML大战需求分析》阅读随笔(一)
UML:Unified Modeling Language(统一建模语言) 作为我专业学科里的一门语言,其目的就是交流,同客户交流,同自己交流. 用图像和文字,详细地讲解将要做的工程的 需求和功能细节 ...
- Mongodb源代码阅读笔记:Journal机制
Mongodb源代码阅读笔记:Journal机制 Mongodb源代码阅读笔记:Journal机制 涉及的文件 一些说明 PREPLOGBUFFER WRITETOJOURNAL WRITETODAT ...
- 【转】Tomcat总体结构(Tomcat源代码阅读系列之二)
本文是Tomcat源代码阅读系列的第二篇文章,我们在本系列的第一篇文章:在IntelliJ IDEA 和 Eclipse运行tomcat 7源代码一文中介绍了如何在intelliJ IDEA 和 Ec ...
- 利用doxygen提高源代码阅读效率
阅读开源项目的源代码是提高自己编程能力的好方法,而有一个好的源代码阅读工具无疑能够让你在阅读源代码时事半功倍.之前找过不少源代码阅读工具,像SourceInsight.sourcenav.scitoo ...
- CI框架源代码阅读笔记5 基准測试 BenchMark.php
上一篇博客(CI框架源代码阅读笔记4 引导文件CodeIgniter.php)中.我们已经看到:CI中核心流程的核心功能都是由不同的组件来完毕的.这些组件类似于一个一个单独的模块,不同的模块完毕不同的 ...
- 淘宝数据库OceanBase SQL编译器部分 源代码阅读--Schema模式
淘宝数据库OceanBase SQL编译器部分 源代码阅读--Schema模式 什么是Database,什么是Schema,什么是Table,什么是列,什么是行,什么是User?我们能够能够把Data ...
- CI框架源代码阅读笔记3 全局函数Common.php
从本篇開始.将深入CI框架的内部.一步步去探索这个框架的实现.结构和设计. Common.php文件定义了一系列的全局函数(一般来说.全局函数具有最高的载入优先权.因此大多数的框架中BootStrap ...
随机推荐
- cmd端口占用查看和关闭端口
cmd——回车,输入netstat -ano——回车,可以查看已占用的端口,记下端口的PID,然后打开任务管理器,点查看,选择列,勾选PID确定,找到对应的PID,结束进程,如果结束不了或者结束后还不 ...
- SSH答疑解惑系列(一)——spring容器是如何启动的
SSH框架十分受欢迎,其中有一个原因就是spring可以和Struts2框架无缝整合.在使用spring时,无需手动创建web容器,而是通过配置文件声明式创建spring容器. 在web应用中,创建s ...
- 绝对定位后a、button等hover状态样式不显示问题
<div class="operate"> <el-button>提交项目</el-button> <el-button type=&qu ...
- delphi数据库进行增加操作时,怎么判断插入的这个值是否已经存在?
//增 procedure TForm1.btnAddClick(Sender: TObject); begin ADOQuery1.Close; ADOQuery1.SQL.Clear; ADOQu ...
- (转)Foundation-性能优化之NSDateFormatter
性能优化之NSDateFormatter 为什么要优化NSDateFormatter? 首先,过度的创建NSDateFormatter用于NSDate与NSString之间转换,会导致App卡顿,打开 ...
- 【bzoj2705】[SDOI2012]Longge的问题 欧拉函数
题目描述 Longge的数学成绩非常好,并且他非常乐于挑战高难度的数学问题.现在问题来了:给定一个整数N,你需要求出∑gcd(i, N)(1<=i <=N). 输入 一个整数,为N. 输出 ...
- 【bzoj2453】维护队列/【bzoj2120】数颜色 分块+二分
题目描述 你小时候玩过弹珠吗? 小朋友A有一些弹珠,A喜欢把它们排成队列,从左到右编号为1到N.为了整个队列鲜艳美观,小朋友想知道某一段连续弹珠中,不同颜色的弹珠有多少.当然,A有时候会依据个人喜好, ...
- 【题解】CQOI2007余数求和
大家都说这题水然而我好像还是调了有一会儿……不过暴力真的很良心,裸的暴力竟然还有60分. 打一张表出来,就会发现数据好像哪里有规律的样子,再仔细看一看,就会发现k/3~k/2为公差为2的等差数列,k/ ...
- BZOJ3132 上帝造题的七分钟 【二维树状数组】
题目 "第一分钟,X说,要有矩阵,于是便有了一个里面写满了0的n×m矩阵. 第二分钟,L说,要能修改,于是便有了将左上角为(a,b),右下角为(c,d)的一个矩形区域内的全部数字加上一个值的 ...
- 如何在数据访问层上提高js的执行效率
本文讲到的是如何从数据访问层面上提高JS 代码的执行效率.总的来讲有以下几条原则: 函数中读写局部变量总是最快的,而全局变量的读取则是最慢的: 尽可能地少用with 语句,因为它会增加with 语句以 ...