• SALALchemy Session与scoped_session的源码分析


    我们发现Session与scoped_session都有一些方法:

    但是scoped_session的源码里面没有设置这些方法让我们从源码里去窥探下源码在哪里设置了这些方法:

    Session里面的方法放在了public_methods里面:

    scoped_session的源码里面没有这些方法?:

    那它怎么实现这些方法的呢?

    我们看到了它的构造方法:

     def __init__(self, session_factory, scopefunc=None):
            """Construct a new :class:`.scoped_session`.
    
            :param session_factory: a factory to create new :class:`.Session`
             instances. This is usually, but not necessarily, an instance
             of :class:`.sessionmaker`.
            :param scopefunc: optional function which defines
             the current scope.   If not passed, the :class:`.scoped_session`
             object assumes "thread-local" scope, and will use
             a Python ``threading.local()`` in order to maintain the current
             :class:`.Session`.  If passed, the function should return
             a hashable token; this token will be used as the key in a
             dictionary in order to store and retrieve the current
             :class:`.Session`.
    
            """
            self.session_factory = session_factory
    
            if scopefunc:
                self.registry = ScopedRegistry(session_factory, scopefunc)
            else:
                self.registry = ThreadLocalRegistry(session_factory)

    第一次进来时,scopefunc是空的。

    走else,

     self.registry = ThreadLocalRegistry(session_factory)
    就会实例化:
    ThreadLocalRegistry。
    class ThreadLocalRegistry(ScopedRegistry):
        """A :class:`.ScopedRegistry` that uses a ``threading.local()``
        variable for storage.
    
        """
    
        def __init__(self, createfunc):
            self.createfunc = createfunc
            self.registry = threading.local()

    里面有两个对象  self.createfunc和registry:

    registry是唯一标识,

    session加上括号就会执行__call__方法:

    因为self.registry.value第一次进入没有值:

    所以走except  就是执行self.createfunc()往前找传的值是session_factory那么session_factory是谁呢?就是我们传入的session,也就是实例化了我们的session。

    就这就会走下面的方法:

    def instrument(name):
        def do(self, *args, **kwargs):
            return getattr(self.registry(), name)(*args, **kwargs)
        return do
    
    for meth in Session.public_methods:
        setattr(scoped_session, meth, instrument(meth))

    方法二:

    我们发现

    class scoped_session(object):
        """Provides scoped management of :class:`.Session` objects.
    
        See :ref:`unitofwork_contextual` for a tutorial.
    
        """
    
        session_factory = None
        """The `session_factory` provided to `__init__` is stored in this
        attribute and may be accessed at a later time.  This can be useful when
        a new non-scoped :class:`.Session` or :class:`.Connection` to the
        database is needed."""
    
        def __init__(self, session_factory, scopefunc=None):
            """Construct a new :class:`.scoped_session`.
    
            :param session_factory: a factory to create new :class:`.Session`
             instances. This is usually, but not necessarily, an instance
             of :class:`.sessionmaker`.
            :param scopefunc: optional function which defines
             the current scope.   If not passed, the :class:`.scoped_session`
             object assumes "thread-local" scope, and will use
             a Python ``threading.local()`` in order to maintain the current
             :class:`.Session`.  If passed, the function should return
             a hashable token; this token will be used as the key in a
             dictionary in order to store and retrieve the current
             :class:`.Session`.
    
            """
            self.session_factory = session_factory
    
            if scopefunc:
                self.registry = ScopedRegistry(session_factory, scopefunc)
            else:
                self.registry = ThreadLocalRegistry(session_factory)

    如果我们给

    scopefunc传值就会走if语句,
    class ScopedRegistry(object):
        """A Registry that can store one or multiple instances of a single
        class on the basis of a "scope" function.
    
        The object implements ``__call__`` as the "getter", so by
        calling ``myregistry()`` the contained object is returned
        for the current scope.
    
        :param createfunc:
          a callable that returns a new object to be placed in the registry
    
        :param scopefunc:
          a callable that will return a key to store/retrieve an object.
        """
    
        def __init__(self, createfunc, scopefunc):
            """Construct a new :class:`.ScopedRegistry`.
    
            :param createfunc:  A creation function that will generate
              a new value for the current scope, if none is present.
    
            :param scopefunc:  A function that returns a hashable
              token representing the current scope (such as, current
              thread identifier).
    
            """
            self.createfunc = createfunc
            self.scopefunc = scopefunc
            self.registry = {}
    
        def __call__(self):
            key = self.scopefunc()
            try:
                return self.registry[key]
            except KeyError:
                return self.registry.setdefault(key, self.createfunc())

    我们看到如果对象加括号就会走__call__方法:

    第一次没有值,就会走except,设置并且实例化session。

    往下方法和方式一一样啦。

    在执行到最后我们要加上一句:

    session.remove()
    我们来看下这句话做了什么?
        def remove(self):
            """Dispose of the current :class:`.Session`, if present.
    
            This will first call :meth:`.Session.close` method
            on the current :class:`.Session`, which releases any existing
            transactional/connection resources still being held; transactions
            specifically are rolled back.  The :class:`.Session` is then
            discarded.   Upon next usage within the same scope,
            the :class:`.scoped_session` will produce a new
            :class:`.Session` object.
    
            """
    
            if self.registry.has():
                self.registry().close()
            self.registry.clear()

    我们进入has看下:

        def has(self):
            return hasattr(self.registry, "value")

     如果有值就执行close方法。

    然后在执行clear方法:

        def clear(self):
            try:
                del self.registry.value
            except AttributeError:
                pass
  • 相关阅读:
    [bug] 未能加载文件或程序集“SIPEPS, Version=6.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35”或它的某一个依赖项。系统找不到指定的文件。
    [MongoDB]索引
    [MongoDB]Profiling性能分析
    [MongoDB]mapReduce
    tms mqtt
    mqtt介绍
    咏南中间件统一的数据序列(还原)类
    支付宝签名
    咏南中间件开始支持中间件桥接
    咏南数据序列(还原)类
  • 原文地址:https://www.cnblogs.com/1a2a/p/8278698.html
Copyright © 2020-2023  润新知