不多说,先上代码

from sqlalchemy.orm import sessionmaker
from sqlalchemy import create_engine
from sqlalchemy.orm import scoped_session engine = create_engine("mysql+pymysql://root:123@127.0.0.1:3306/s6", max_overflow=0, pool_size=5)
Session = sessionmaker(bind=engine) # session = Session()
session = scoped_session(Session)
 obj1 = Users(name="alex1")
 session.add(obj1)
  
 # 提交事务
 session.commit()
 # 关闭session
 session.close()

  在上面代码中,从连接池中拿连接的时候,Session直接实例化,或者scoped_session进行实例化也可以

  而且调用时,方法名都是一样的,比如session.add(),我们会猜他两是继承关系

  但实际是class scoped_session(object),并没有继承Session,而且在scoped_session里也没有找到add方法和commit方法... 那它怎么实现的?

  

  在scoped_session类下面,有个for循环,其中public_methods,在这里面有我们想看到的add,commit方法,上面把每个方法都设置到scoped_session类里,还要看下instrument(meth)到底是个啥玩意?

    public_methods = (
'__contains__', '__iter__', 'add', 'add_all', 'begin', 'begin_nested',
'close', 'commit', 'connection', 'delete', 'execute', 'expire',
'expire_all', 'expunge', 'expunge_all', 'flush', 'get_bind',
'is_modified', 'bulk_save_objects', 'bulk_insert_mappings',
'bulk_update_mappings',
'merge', 'query', 'refresh', 'rollback',
'scalar')

  在这个函数最终返回了一个do函数,并把name,也就是函数名传了进入实现闭包

def instrument(name):
def do(self, *args, **kwargs):
return getattr(self.registry(), name)(*args, **kwargs)
return do

  所以当执行session.add时,它会去执行do函数,里面封装的name就是add

  do函数中self.registry是个啥玩意呢?其中self指的是scoped_session对象,所以我们可以去看scoped_session进行实例化是都干了些啥

        #session_factory就是传入的Session = sessionmaker(bind=engine)
self.session_factory = session_factory if scopefunc:
self.registry = ScopedRegistry(session_factory, scopefunc)
else:#scopefunc此时没值,所以走这里
self.registry = ThreadLocalRegistry(session_factory)

  我们会看到我们需要的self.registry就在上面代码中,那现在主要ThreadLocalRegistry实例化后返回个啥?

    def __init__(self, createfunc):
self.createfunc = createfunc
self.registry = threading.local()

  createfunc就是传入的session_factory,也就是Session,所以scoped_session对象的registry,是一个ThreadLocalRegistry对象,封装了Session和local对象

  所以self.registry()会执行ThreadLocalRegistry里的__call__方法

    def __call__(self):
try:
return self.registry.value #刚开始value没值,会报错
except AttributeError:
val = self.registry.value = self.createfunc() #走这里Session(),也就是数据库连接操作句柄,并把句柄放入local中
return val

  so,self.registry()得到的就是数据库操作句柄,所以do函数里最终还是获取到Session里的方法,并执行

  当然第一次add操作,会实例化,第二次就直接去local中取,就不走异常分支了

  所以这种方式在线程上是更安全的

SQLAlchemy中scoped_session实现线程安全的更多相关文章

  1. SQLAlchemy 中的 Session、sessionmaker、scoped_session

    目录 一.关于 Session 1. Session是缓存吗? 2. Session作用: 3. Session生命周期: 4. Session什么时候创建,提交,关闭? 4. 获取一个Session ...

  2. flask SQLAlchemy中一对多的关系实现

    SQLAlchemy是Python中比较优秀的orm框架,在SQLAlchemy中定义了多种数据库表的对应关系, 其中一对多是一种比较常见的关系.利用flask sqlalchemy实现一对多的关系如 ...

  3. 重新想象 Windows 8 Store Apps (42) - 多线程之线程池: 延迟执行, 周期执行, 在线程池中找一个线程去执行指定的方法

    [源码下载] 重新想象 Windows 8 Store Apps (42) - 多线程之线程池: 延迟执行, 周期执行, 在线程池中找一个线程去执行指定的方法 作者:webabcd 介绍重新想象 Wi ...

  4. Java中的守护线程和非守护线程(转载)

    <什么是守护线程,什么是非守护线程> Java有两种Thread:"守护线程Daemon"(守护线程)与"用户线程User"(非守护线程). 用户线 ...

  5. springmvc中request的线程安全问题

    SpringMvc学习心得(四)springmvc中request的线程安全问题 标签: springspring mvc框架线程安全 2016-03-19 11:25 611人阅读 评论(1) 收藏 ...

  6. Unity 中 使用c#线程

    使用条件   天下没有免费的午餐,在我使用unity的那一刻,我就感觉到不自在,因为开源所以不知道底层实现,如果只是简单的做点简单游戏,那就无所谓的了,但真正用到实际地方的时候,就会发现一个挨着一个坑 ...

  7. Java中的守护线程 & 非守护线程(简介)

    Java中的守护线程 & 非守护线程 守护线程 (Daemon Thread) 非守护线程,又称用户线程(User Thread) 用个比较通俗的比如,任何一个守护线程都是整个JVM中所有非守 ...

  8. HttpApplication中的异步线程

    一.Asp.net中的线程池设置 在Asp.net的服务处理中,每当服务器收到一个请求,HttpRuntime将从HttpApplication池中获取一个HttpApplication对象处理此请求 ...

  9. c#中如何跨线程调用windows窗体控件

    c#中如何跨线程调用windows窗体控件?   我们在做winform应用的时候,大部分情况下都会碰到使用多线程控制界面上控件信息的问题.然而我们并不能用传统方法来做这个问题,下面我将详细的介绍.首 ...

随机推荐

  1. MySQL Date函数的正确用法

    以下的文章主要介绍的是MySQL Date函数的实际应用其中包括如何获取当前时间的具体操作,Unix时间的具体应用,时间前后.时间间隔与时间转换的实际内容描述,以下就是文章的主要内容. MySQL D ...

  2. jQuery checkbox选中问题之prop与attr注意点分析

    $(function () {   // 全选   $("#btnCheckAll").bind("click", function () {     $(&q ...

  3. 51地图标注接口(EZMarker API)

    功能 在很多时候,您需要您的用户标出一个位置,比如:一个房地产网站,用户在登记新楼盘的时候,就需要在地图上标出这个楼盘的位置,这个时候就可以用到本接口. 地图标注接口(EZMarker API)是我要 ...

  4. 加L“”

    error C2665: “AfxMessageBox”: 2 个重载中没有一个可以转换所有参数类型 初学.net,编写如下代码运行,竟然提示错误(error C2665: “AfxMessageBo ...

  5. JavaScript------去掉Array中重复值

    转载: http://blog.csdn.net/teresa502/article/details/7926796 代码: // 删除数组中重复数据 function removeDuplElem( ...

  6. UVA 1341 - Different Digits(数论)

    UVA 1341 - Different Digits 题目链接 题意:给定一个正整数n.求一个kn使得kn上用的数字最少.假设同样,则输出值最小的 思路: 首先利用鸽笼原理证明最多须要2个数字去组成 ...

  7. Linux内核中断处理体系分析

    前一篇博文中:linux内核初始化阶段通过early_trap_init()函数完毕了把异常向量复制到0xFFFF0000開始的地方,这些异常向量大部分指向通过vector_stub宏定义的那段代码. ...

  8. 什么是LTE?

    LTE是英文Long Term Evolution的缩写.LTE也被通俗的称为3.9G,具有100Mbps的数据下载能力,被视作从3G向4G演进的主流技术.它改进并增强了3G的空中接入技术,采用OFD ...

  9. ASP代码审计学习笔记 -3.上传漏洞

    1.ASP上传过程抓包分析: POST /4.asp HTTP/1.1 Host: 192.168.1.102 User-Agent: Mozilla/5.0 (Windows NT 10.0; WO ...

  10. ASP代码审计学习笔记 -2.XSS跨站脚本

    XSS漏洞: 漏洞代码: <% xss=request("xss") response.write(xss) %> 漏洞利用: 漏洞修复: Server.HTMLEnc ...