#sqlalchemy之create_engine和session

orm

实质上,一个O/R Mapping会为你生成DAL。(即为数据访问层(Data Access Layer)。其功能主要是负责数据库的访问。)用O/R Mapping保存,删除,读取对象,O/R Mapping负责生成SQL,你只需要关心对象就好。

一般的ORM包括以下四部分:

  • 一个对持久类对象进行CRUD操作的API;// crud:增删查改
  • 一个语言或API用来规定与类和类属性相关的查询;
  • 一个规定mapping metadata的工具;
  • 一种技术可以让ORM的实现同事务对象一起进行dirty checking, lazy association fetching以及其他的优化操作

SQLAlchemy介绍

Python中最有名的ORM架构就是SQLAlchemy,我们主要就是来学习SQLAlchemy的使用

初始化连接

from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
self.engine = create_engine(conn['conn_str'],
pool_size=16,
pool_pre_ping=True)
self.session = sessionmaker(bind=self.engine)

create_engine()用来初始化数据库连接。SQLAlchemy用一个字符串表示连接信息:

'数据库类型+数据库驱动名称://用户名:口令@机器地址:端口号/数据库名'

数据库连接池的使用

from sqlalchemy.orm import sessionmaker
from sqlalchemy import create_engine
from sqlalchemy.orm import scoped_session
from models import Student,Course,Student2Course engine = create_engine(
"mysql+pymysql://root:123456@127.0.0.1:3306/s9day120?charset=utf8",
max_overflow=0, # 超过连接池大小外最多创建的连接
pool_size=5, # 连接池大小
pool_timeout=30, # 池中没有线程最多等待的时间,否则报错
pool_recycle=-1 # 多久之后对线程池中的线程进行一次连接的回收(重置)
)
SessionFactory = sessionmaker(bind=engine)
session = scoped_session(SessionFactory) def task():
""""""
# 方式一:
"""
# 查询
# cursor = session.execute('select * from users')
# result = cursor.fetchall() # 添加
cursor = session.execute('INSERT INTO users(name) VALUES(:value)', params={"value": 'wupeiqi'})
session.commit()
print(cursor.lastrowid)
"""
# 方式二:
"""
# conn = engine.raw_connection()
# cursor = conn.cursor()
# cursor.execute(
# "select * from t1"
# )
# result = cursor.fetchall()
# cursor.close()
# conn.close()
""" # 将连接交还给连接池
session.remove() from threading import Thread for i in range(20):
t = Thread(target=task)
t.start()

转自http://www.cnblogs.com/lianggege123/articles/9210147.html

session 是ORM和db交互的方式

  1. 包装了engine的连接
  2. 包装了对象的identity map(类似cache, 保存了由表名和主键确定的唯一对象列表)
  3. 包装了transaction

使用sessionmaker创建session

sessionmaker类保证创建出同样配置的session. 应当全局被使用一次.

from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
engine = create_engine('sqlite:///:memory:')
Session = sessionmaker(bind=engine)
session = Session()

Session状态

https://stackoverflow.com/questions/8645250/how-to-close-sqlalchemy-connection-in-mysql

http://docs.sqlalchemy.org/en/latest/orm/session_state_management.html

一个实例在session中可能有以下状态:

Transient

Pending

Persiste

Deleted

Detached

session.identity_map保存了一个WeakInstanceDict

key是database_identity(model的class, primary_key); value是InstanceState

Expunge:

将对象从session中移除,

sending persistent instances to the detached state, and pending instances to the transient state

对象实例会有一个dict对象保存属性, 这些属性类似缓存.

对象过期的时候(比如commit之后, 由于不知道事务的执行情况), dict内容会作废, 再次访问对象实例的属性, 会触发lazy load. 从数据库加载这些属性. 这个时候如果session已经close就会报错.

可以在commit之前, 用expunge, 将对象实例从session移除. 这是对象实例可以正常使用. 但是无法加载未加载的属性, 也无法加载expired的属性.

mysql gone away

http://docs.sqlalchemy.org/en/latest/faq/connections.html?highlight=gone%20away

http://docs.sqlalchemy.org/en/latest/core/pooling.html#pool-disconnects

The primary cause of this error is that the MySQL connection has timed out and has been closed by the server. The MySQL server closes connections which have been idle a period of time which defaults to eight hours. To accommodate this, the immediate setting is to enable the create_engine.pool_recycle setting

For the more general case of accommodating database restarts and other temporary loss of connectivity due to network issues, connections that are in the pool may be recycled in response to more generalized disconnect detection techniques.

这时有两种方式解决

  • 悲观方式: 每次执行语句前先执行select

    1 或者通过pre_ping参数
engine = create_engine("mysql+pymysql://user:pw@host/db", pool_pre_ping=True)
  • 乐观方式: 执行失败后重试
from sqlalchemy import create_engine, exc
e = create_engine(...)
c = e.connect() try:
# suppose the database has been restarted.
c.execute("SELECT * FROM table")
c.close()
except exc.DBAPIError, e:
# an exception is raised, Connection is invalidated.
if e.connection_invalidated:
print("Connection was invalidated!") # after the invalidate event, a new connection
# starts with a new Pool
c = e.connect()
c.execute("SELECT * FROM table")

转自(https://www.jianshu.com/p/96e393afd721

添加点web里的session,对比一下

Cookie

cookie是浏览器保存在用户电脑上的一小段文本,用来保存用户在网站上的必要的信息。Web页面或服务器告诉浏览器按照一定的规范存储这些信息,并且在以后的所有请求中,这些信息就会自动加在http请求头中发送给服务器,服务器根据这些信息判断不同的用户。并且cookie本身是安全的。



比如:

Cookie: name=value; name1=value1; name2=value2/pre>

Session

session的作用和cookie差不多,也是用来解决Http协议不能维持状态的问题。但是session只存储在服务器端的,不会在网络中进行传输,所以较cookie来说,session相对安全一些。但是session是依赖cookie的,当用户访问某一站点时,服务器会为这个用户产生唯一的session_id,并把这个session_id以cookie的形式发送到客户端,以后的客户端的所有请求都会自动携带这个cookie(前提是浏览器支持并且没有禁用cookie)。

禁用cookie时如何使用session

有些时候,为了安全浏览器会禁用cookie,这时可以用传参的方式将session_id发送到服务器,session可以照常工作.

sqlalchemy之create_engine和session的更多相关文章

  1. SqlAlchemy 中操作数据库时session和scoped_session的区别(源码分析)

    原生session: from sqlalchemy.orm import sessionmaker from sqlalchemy import create_engine from sqlalch ...

  2. SQLAlchemy 中的 Session、sessionmaker、scoped_session

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

  3. SQLAlchemy中Model.query和session.query(Model)的区别

    我们使用Flask 0.11.1,Flask-SQLAlchemy 2.1使用PostgreSQL作为DBMS. 示例使用以下代码更新数据库中的数据: entry = Entry.query.get( ...

  4. sqlalchemy 多线程 创建session

    1.基于threding.local,推荐使用 from sqlalchemy.orm import sessionmaker from sqlalchemy import create_engine ...

  5. flask 源码专题(五):SqlAlchemy 中操作数据库时session和scoped_session的区别

    1原生session: from sqlalchemy.orm import sessionmaker from sqlalchemy import create_engine from sqlalc ...

  6. SQlALchemy session详解

    系列文章: Python SQLAlchemy入门教程 概念 session用于创建程序和数据库之间的会话,所有对象的载入和保存都需通过session对象 . 通过sessionmaker调用创建一个 ...

  7. sqlalchemy 源码分析之create_engine引擎的创建

    引擎是sqlalchemy的核心,不管是 sql core 还是orm的使用都需要依赖引擎的创建,为此我们研究下,引擎是如何创建的. from sqlalchemy import create_eng ...

  8. sqlalchemy学习

    sqlalchemy官网API参考 原文作为一个Pythoner,不会SQLAlchemy都不好意思跟同行打招呼! #作者:笑虎 #链接:https://zhuanlan.zhihu.com/p/23 ...

  9. tornado+sqlalchemy+celery,数据库连接消耗在哪里

    随着公司业务的发展,网站的日活数也逐渐增多,以前只需要考虑将所需要的功能实现就行了,当日活越来越大的时候,就需要考虑对服务器的资源使用消耗情况有一个清楚的认知.     最近老是发现数据库的连接数如果 ...

随机推荐

  1. PHP FILTER_SANITIZE_NUMBER_FLOAT 过滤器

    定义和用法 FILTER_SANITIZE_NUMBER_FLOAT 过滤器删除浮点数中所有非法的字符. 该过滤器默认允许所有数字以及 + - Name: "number_float&quo ...

  2. Java中连接MySql数据库的例子

    Java中连接MySql数据库的例子: package com.joinmysql.demo; import java.sql.DriverManager; import java.sql.Resul ...

  3. move_base 分层代价地图的作用(翻译)

    A. 标准层 ​ Static Map Layer:为了做全局规划,机器人需要一个超越其传感器的地图,以了解墙壁和其他静态障碍物的位置. 静态地图可以先用SLAM算法生成,也可以从架构图中创建. 当层 ...

  4. JSON.NET与LINQ序列化示例教程

    1.手动创建JSON对象和数组 JSON格式主要包括对象和数组两种形式,在JSON.NET中分别用JArray和JObject表示,属性用JProperty表示,属性值用 JValue表示,这些对象都 ...

  5. [NOIP模拟测试9]题(Problem) 题解 (组合数全家桶+dp)

    达哥送分给我我都不要,感觉自己挺牛批. $type=0:$ 跟visit那题类似,枚举横向移动的步数直接推公式: $ans=\sum C_n^i \times C_i^{\frac{i}{2}} \t ...

  6. 【系统安全性】四、认证Authentication

    四.认证Authentication 1.为什么要认证 对请求.数据进行认证,判断伪造的数据 HTTP请求很脆弱,抓包软件很强大,容易伪造身份,非法获取数据 2.摘要认证 对象:客户端参数.服务端响应 ...

  7. NYOJ 737 (石子合并)

    该题是一道DP题,核心思想如下: 某个区间一定是这个区间内的某两个子区间合成的(这两个子区间互补,即这两个区间加起来等于大区间), 所以我们枚举所有的情况,取个最大值即可.因为最初是从2堆石子开始无法 ...

  8. robotframework 时间控件的操作的几种方法总结。

  9. Vue中时间的设置

    设置默认属性ct_month: null 方法: //默认显示今天getdatatime(){ this.ct_month= new Date(); }, //默认显示昨天getdatatime(){ ...

  10. DLL 调用 对话框 以及 如何获取调用dll 应用程序(窗口程序)的窗口句柄

    1.一般创建需要的窗口,转换成相应的窗口类: 声明一个导出函数,来处理窗口的显示,如: CTest test; extern "C" __declspec(dllexport) v ...