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 ...
随机推荐
- Introduction to TCP/IP
目录 First Week DHCP 子网掩码 ip路由表 Second Week ipv4 ipv6 TCP和UDP Third Week NAT RPC FTP E-mail Fouth Week ...
- webmagic 二次开发爬虫 爬取网站图片
webmagic的是一个无须配置.便于二次开发的爬虫框架,它提供简单灵活的API,只需少量代码即可实现一个爬虫. webmagic介绍 编写一个简单的爬虫 webmagic的使用文档:http://w ...
- Chromium之文件类型
.grp: Generate your project. 是由Json(JavaScript Object Notation)(or Python?)来解析,根据环境(OS,Compiler..)来生 ...
- QT启动一个工程
功能描述: 模拟如下页面. 当输入一个字符串时打开对应的应用程序. 实现方法: 1. 建立工程 2. 界面编辑: 3. 在test1.h中添加slot声明 4. test1.cpp中添加slot定义 ...
- 项目常用解决方案之SystemSetting.xml文件的修改与读取
Winform及WPF项目中经常会用到类似SystemSetting.xml等类似的文件用于保存CLIENT的数据,比如登录过的用户名或密码以及其他设置.所以就想到一个解决方法,可以用到所有有此需求的 ...
- spring笔记二
DI—Dependency Injection,即“依赖注入”:组件之间依赖关系由容器在运行期决定,形象的说,即由容器动态的将某个依赖关系注入到组件之中.依赖注入的目的并非为软件系统带来更多功能,而是 ...
- [POJ1631]Bridging signals
题目大意:不知,根据样例猜测为最长上升子序列(竟然还对了) 题解:$O(n log_2 n)$,求二维偏序,(q为存答案的序列,a存原序列,len为答案) for(int i = 1; i <= ...
- AtCoder Code Festival 2017 Team Relay J - Indifferent
题目大意:共$2n$个价格$p_i$.两人轮流取.你每次取最大的,对方每次随机取.问你取的期望和是多少. 题解:从小到大排序,$\sum\limits_{i=0}^{2n-1} \frac{i*p_i ...
- React生命周期总结
React的生命周期总共8个钩子,三个will,两个Did,一个RecciveProps,一个ShouldUpdate,一个render.分为三个阶段,分别是 装载 Mounting更新 Updati ...
- 深入理解Java虚拟机—内存管理机制
前面说过了类的加载机制,里面讲到了类的初始化中时用到了一部分内存管理的知识,这里让我们来看下Java虚拟机是如何管理内存的. 先让我们来看张图 有些文章中对线程隔离区还称之为线程独占区,其实是一个意思 ...