不多说,先上代码

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. 本来想用jsonp来跨域请求的,但sb写接口的,不改返回值。。。只得在后台请求接口了。。。

    string url = "ssss.com";//demo里的是get请求 HttpWebResponse w = HttpHelper.CreateGetHttpRespons ...

  2. openstack中nova组件Hypervisors、Floating_ips的全部python API 汇总

    感谢朋友支持本博客,欢迎共同探讨交流,因为能力和时间有限.错误之处在所难免,欢迎指正! 假设转载.请保留作者信息. 博客地址:http://blog.csdn.net/qq_21398167 原博文地 ...

  3. iperf/netperf网络性能测试工具、Wireshark网络包分析工具

    iperf   http://www.linuxidc.com/Linux/2014-05/101160.htm netperf  http://www.linuxidc.com/Linux/2013 ...

  4. java jdk-awt.font在centos上中文乱码的问题, 安装中文字体

    有需求生成一个二维码,并且有一段文本说明,但是使用awt.font来生成中文时,一直存在乱码的问题.网上的解决办法有几种,但是在centos上亲测有用的就是如下的方法. Java代码如下:new ja ...

  5. 火云开发课堂 - 《使用Cocos2d-x 开发3D游戏》系列 第四节:3D公告板

    <使用Cocos2d-x 开发3D游戏>系列在线课程 第四节:3D公告板 视频地址:http://edu.csdn.net/course/attend/1330/20804 交流论坛:mo ...

  6. JAVA语言基础内部测试题(50道选择题)

    JAVA语言基础内部测试题 选择题(针对以下题目,请选择最符合题目要求的答案,针对每一道题目,所有答案都选对,则该题得分,所选答案错误或不能选出所有答案,则该题不得分.)(每题2分) 没有注明选择几项 ...

  7. Java精选笔记_会话技术

    会话及其会话技术 会话概述 指的是一个客户端(浏览器)与Web服务器之间连续发生的一系列请求和响应过程. 会话:从浏览器开启到浏览器关闭.会话技术:用来保存在会话期间 浏览器和服务器所产生的数据. 在 ...

  8. Spring装配Bean的过程

    首先说一个概念:“懒加载” 懒加载:就是我们在spring容器启动的是先不把所有的bean都加载到spring的容器中去,而是在当需要用的时候,才把这个对象实例化到容器中. spring配置文件中be ...

  9. 管理开机启动:chkconfig

    CentOS 6 如何设置服务开机启动: [root@localhost ~]$ ls /etc/init.d/httpd # /etc/init.d/目录下必须有启动脚本 [root@localho ...

  10. 高性能LAMP程序设计

    高性能LAMP程序设计 原文地址: http://www.infoq.com/cn/presentations/fcq-high-performance-lamp-programming 演讲稿: h ...