这次阅读的,是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,下一次再说。
 

最新文章

  1. cosine similarity
  2. python 模块库
  3. H5新特性websocket
  4. OpenGL笔试题
  5. ASP.NET文章目录导航
  6. Btrace入门到熟练小工完全指南
  7. BringWindowToTop(), SetForegroundWindow(), SetActiveWindow()
  8. git 拆库 切库 切分 子目录建库
  9. uml系列(八)——部署图与构件图
  10. DL4NLP —— seq2seq+attention机制的应用:文档自动摘要(Automatic Text Summarization)
  11. 将matlab数据保存为excel文件
  12. shell中的函数、数组、报警系统脚本
  13. Ubuntu命令行快捷启动Matlab
  14. React时间组件(时分秒补0)页面全局引用
  15. Codeforces 950 C. Zebras
  16. .NET 黑魔法 - asp.net core 自定义格式的响应
  17. sparkSQL以JDBC为数据源
  18. Mybatis批量更新和插入
  19. 牛客网练习赛43-C(图论)
  20. 【LLVM笔记】0x00 初识LLVM 链接类型

热门文章

  1. 基于twemproxy和vip实现redis集群的无感知弹性扩容
  2. epc笔记
  3. OpenCV膨胀和腐蚀示例代码
  4. charles和Fiddler感觉哪个更好用
  5. capacilitys 持续集成
  6. JSP乱码问题
  7. 【NOIP模拟赛】天神下凡 动态开点线段树
  8. 如何在Javascript中利用封装这个特性
  9. Ubuntu下使用find / -name aaa* 提示“find: 路径必须在表达式之前: XXXX”
  10. POJ2516:Minimum Cost(最小费用最大流)