原生session:

from sqlalchemy.orm import sessionmaker

from sqlalchemy import create_engine

from sqlalchemy应用.models import Users

engine = create_engine(

"mysql+pymysql://root:root@127.0.0.1:3306/pro6?charset=utf8",

max_overflow=0, # 超过连接池大小外最多创建的连接

pool_size=5, # 连接池大小

)

#from sqlalchemy.orm.session import Session

SessionF = sessionmaker(bind=engine)

session = SessionF()

print(session)

obj1 = Users(name='ctz', email='49274573@qq.com', extra='aaaa')

session.add(obj1)

session.commit()

session.close()

问题:由于无法提供线程共享功能,所以在开发时要注意,要给每个线程都创建自己的session

打印sesion可知他是sqlalchemy.orm.session.Session的对象

查看Session的源码 可得到:

class Session(_SessionClassMethods):

"""Manages persistence operations for ORM-mapped objects.

The Session's usage paradigm is described at :doc:`/orm/session`.

"""

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')

2.scoped_session

from sqlalchemy.orm import sessionmaker

from sqlalchemy.ext.declarative import declarative_base

from sqlalchemy import create_engine

from sqlalchemy应用.models import Users

from sqlalchemy.orm import scoped_session

engine=create_engine(

"mysql+pymysql://root:root@127.0.0.1:3306/pro6?charset=utf8",

max_overflow=0, # 超过连接池大小外最多创建的连接

pool_size=5, # 连接池大小

)

SessionF=sessionmaker(bind=engine)

#scoped_session封装了两个值 Session 和 registry,registry加括号就执行了ThreadLocalRegistry的__call__方法,如果

# 当前本地线程中有session就返回session,没有就将session添加到了本地线程

#self.registry()=session

session=scoped_session(SessionF)

print(session)

obj1=Users(name='ctz',email='49274573@qq.com',extra='aaaa')

session.remove()

session.query_property()

优点:支持线程安全,为每个线程都创建一个session:

两种方式:通过本地线程Threading.Local()和创建唯一标识的方法(参考flask请求源码)

源码分析:

首先我们在scoped_session中放入了Sesion对象

SessionF=sessionmaker(bind=engine)

session=scoped_session(Session)

一、scoped_session类中

class scoped_session(object):

session_factory = None

def __init__(self, session_factory, scopefunc=None):

#传递过来的那个Session对象

self.session_factory = session_factory

#scopefunc唯一标示函数

if scopefunc:

self.registry = ScopedRegistry(session_factory, scopefunc)

else:

self.registry = ThreadLocalRegistry(session_factory)

第一次进来scopefunc唯一标识为None,我们将Session作为参数传递到ThreadLocalRegistry中,

ThreadLocalRegistry类中

class ThreadLocalRegistry(ScopedRegistry):

"""A :class:`.ScopedRegistry` that uses a ``threading.local()``

variable for storage.

"""

def __init__(self, createfunc):

#传递过来的那个Session对象

self.createfunc = createfunc

self.registry = threading.local()

#scoped_session.registry()后执行

def __call__(self):

try:

#如果本地线程中有值的话直接将值返回,

return self.registry.value

except AttributeError:

#没有值的话就示例话Session(),并将他存到本地线程中,并把实例的对象返回

#相当于Session()后的对象加到了本地线程中

val = self.registry.value = self.createfunc()

return val

其中__call__()只有当scoped_session.registry加括号执行

那我们怎么调用那些方法呢?

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))

其中 Session就是sqlalchemy.orm.session.Session

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')

在instrument函数中

self.registry()帮我们执行了ThreadLocalRegistry中的___call__方法,拿到了sesion对象

方法源码示例:

def has(self):

return hasattr(self.registry, "value")

def remove(self):

if self.registry.has():

self.registry().close()

self.registry.clear()

实际两种方式原理都是一样的都是第一种,只是第二种将session放到了本地线程中,为每一个进程都设置了一个session,实现了线程安全

pbp 读取 mysql数据_SqlAlchemy 中操作数据库时session和scoped_session的区别(源码分析)...相关推荐

  1. java连接本地数据库命令_Java操作数据库时一次连接只能执行一条SQL命令

    Java操作数据库时一次连接只能执行一条SQL命令 答:× 全面深化改革要攻坚涉险,必须坚持正确的思想方法,不断探索和把握全面深化改革的内在规律,特别是要把握和处理好全面深化改革中的等重大关系 答:整 ...

  2. 使用U盘传数据时操作系统做了什么(源码分析)

    一.背景 学习linux文件系统时考虑一个具体的问题:我们经常会用U盘传输东西到计算机中.当我们把U盘插入到一台计算机上,并且从U盘中复制文件到计算机里,然后卸载U盘,将U盘拔出.操作系统在这一连串过 ...

  3. Java Review - 线程池中使用ThreadLocal不当导致的内存泄漏案例源码分析

    文章目录 概述 Why 内存泄露 ? 在线程池中使用ThreadLocal导致的内存泄漏 概述 ThreadLocal的基本使用我们就不赘述了,可以参考 每日一博 - ThreadLocal VS I ...

  4. pbp 读取 mysql数据_pbp: Django项目开发,个人博客网站类。

    pbp 项目介绍 首个Django项目开发,个人博客网站类. 框架模型 Django 运行平台 Linux 安装部署 1.安装Python3环境 CentOS 7 curl -o /etc/yum.r ...

  5. eclipse读取mysql数据乱码_eclipse从数据库获取数据时控制台乱码问题

    最近在学习HQL的时候,想从数据库获取数据时eclipse控制台乱码,一开始以为是控制台设置的编码有问题,然后就修改了控制台的编码,run->run Configurations->com ...

  6. 关于OleDbCommand中操作数据库的几种方法的区别

    在vb.net中利用OleDb的OleDbCommand类操作数据库,有以下这些方法: ExecuteNoQuery() 返回值类型integer,常用来执行增删改操作,返回操作影响的行数 Execu ...

  7. Vue 3 中 v-if 和 v-show 指令实现的原理(源码分析)

    前言 又回到了经典的一句话:"知其然,而后使其然".相信大家对 Vue 提供 v-if 和 v-show 指令的使用以及对应场景应该都滚瓜烂熟了.但是,我想仍然会有很多同学对于 v ...

  8. c 读取mysql中表中数据_c#读取MySQL数据表中的内容

    using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin ...

  9. php获取mysql数据菜鸟_PHP操作数据库

    function con(){ // MYSQL连接参数 $dsn='mysql:host=127.0.0.1;dbname=hello;charset=utf8;port=3306;'; $dbna ...

最新文章

  1. Mycat实现垂直拆分与水平拆分
  2. Linux中mysql的操作
  3. React Native组件开发指南
  4. nginx源码初读(1)--让烦恼从数据结构开始(ngx_cdecl/ngx_int/ngx_log)
  5. ubuntu19.10安装haroopad软件
  6. UVa 11374 机场快线
  7. python读取math_怎么使用python安装math库?怎么用?
  8. 记录ie下报XMLHttpRequest: 网络错误 0x80070005, 拒绝访问。
  9. json生成shp_使用JS把shapefile地图数据转换为geojson格式
  10. Nginx如何配置静态文件过期时间
  11. PHP魔术方法和魔法变量详解
  12. php常用的几个算法
  13. Dijkstra最短路径
  14. proteus8找不到isis
  15. IP变更导致fdfs文件上传服务不可用解决流程
  16. win10安装串口驱动pl2303 ch340 cp2102时安装不上的一些解决办法
  17. JavaScript实现左右分栏宽度拉伸
  18. 如何通过拍照识别植物?试试这几个软件
  19. 区块链开发先达区块链跨境支付系统解决方案
  20. 卷积神经网络参数量和计算量内存计算

热门文章

  1. SpringBoot中常见的错误
  2. Centos6.5 安装配置docker
  3. leetcode63. Unique Paths II
  4. BZOJ2498 : Xavier is Learning to Count
  5. DRP问题集结(一)-Tomcat无法启动,报错java.lang.NoClassDefFoundError: org/apache/juli/logging/LogFactory...
  6. Android系统Google Maps开发实例浅析
  7. 理解Java动态代理(1)—找我还钱?我出钱要你的命
  8. html Frame、Iframe、Frameset 的区别 详细出处参考:http://www.jb51.net/web/22785.html
  9. 干粮 -- 计算机程序设计艺术(The Art of Computer Design) - 2
  10. 用于参考的学生信息管理系统(数据库简单 可自己参考创建)