GVKun编程网logo

我如何知道是否可以禁用SQLALCHEMY_TRACK_MODIFICATIONS?(怎么知道sql是否可以执行)

20

本文将介绍我如何知道是否可以禁用SQLALCHEMY_TRACK_MODIFICATIONS?的详细情况,特别是关于怎么知道sql是否可以执行的相关信息。我们将通过案例分析、数据研究等多种方式,帮助您

本文将介绍我如何知道是否可以禁用SQLALCHEMY_TRACK_MODIFICATIONS?的详细情况,特别是关于怎么知道sql是否可以执行的相关信息。我们将通过案例分析、数据研究等多种方式,帮助您更全面地了解这个主题,同时也将涉及一些关于FAQ(80):java.util.ConcurrentModificationException at java.util.ArrayList$Itr.checkForComodification、flask+flask_sqlalchemy+flask_script+flask_migrate 创建一个flask项目(一)、flask_sqlalchemy model序列化、flask_sqlalchemy 查询结果转dict 终极解决方案的知识。

本文目录一览:

我如何知道是否可以禁用SQLALCHEMY_TRACK_MODIFICATIONS?(怎么知道sql是否可以执行)

我如何知道是否可以禁用SQLALCHEMY_TRACK_MODIFICATIONS?(怎么知道sql是否可以执行)

每次我运行使用Flask-
SQLAlchemy的应用程序时,都会收到以下警告,提示该SQLALCHEMY_TRACK_MODIFICATIONS选项将被禁用。

/home/david/.virtualenvs/flask-sqlalchemy/lib/python3.5/site-packages/flask_sqlalchemy/__init__.py:800: UserWarning: SQLALCHEMY_TRACK_MODIFICATIONS adds significant overhead and will be disabled by default in the future.  Set it to True to suppress this warning.  warnings.warn(''SQLALCHEMY_TRACK_MODIFICATIONS adds significant overhead and will be disabled by default in the future.  Set it to True to suppress this warning.'')

我试图找出此选项的作用,但Flask-SQLAlchemy文档尚不清楚该跟踪的用途。

SQLALCHEMY_TRACK_MODIFICATIONS

如果设置为True(默认值),Flask-SQLAlchemy将跟踪对象的修改并发出信号。这需要额外的内存,如果不需要,可以将其禁用。

如何确定我的项目是否需要,SQLALCHEMY_TRACK_MODIFICATIONS = True或者是否可以安全地禁用此功能并在服务器上节省内存?

答案1

小编典典

您的应用程序很可能没有使用Flask-SQLAlchemy事件系统,因此可以安全地关闭它。您需要审核代码以进行验证-
您正在寻找与models_committedbefore_models_committed挂钩的任何内容。如果确实发现您正在使用Flask-
SQLAlchemy事件系统,则可能应该更新代码以改为使用SQLAlchemy的内置事件系统。

从Flask-SQLAlchemy 2.1开始None,默认值为,这是一个伪造的值,因此事件系统 被禁用
。在旧版本中,默认值为True,因此您需要明确禁用它。

但是,在这两种情况下,除非将警告明确设置为,否则警告都不会消失False。为此,请添加:

SQLALCHEMY_TRACK_MODIFICATIONS = False

到您的应用程序配置。


背景-警告告诉您的是以下内容:

Flask-
SQLAlchemy有其自己的事件通知系统,该系统在SQLAlchemy之上分层。为此,它跟踪对SQLAlchemy会话的修改。这会占用额外的资源,因此该选项SQLALCHEMY_TRACK_MODIFICATIONS允许您禁用修改跟踪系统。

更改的理由有三点:

  1. 使用Flask-SQLAlchemy的事件系统的人并不多,但是大多数人没有意识到他们可以通过禁用它来节省系统资源。因此,更明智的默认设置是禁用它,想要它的人可以打开它。

  2. Flask-SQLAlchemy中的事件系统存在相当多的错误(请参阅下面提到的请求请求中与之相关的问题),需要为很少有人使用的功能进行额外的维护。

  3. 在v0.7中,SQLAlchemy本身添加了功能强大的事件系统,包括创建自定义事件的功能。理想情况下,Flask-SQLAlchemy事件系统除了创建一些自定义的SQLAlchemy事件挂钩和侦听器外,无所不用其事,然后让SQLAlchemy自己管理事件触发器。

您可以在有关开始触发此警告的请求请求的讨论中看到更多信息。

FAQ(80):java.util.ConcurrentModificationException at java.util.ArrayList$Itr.checkForComodification

FAQ(80):java.util.ConcurrentModificationException at java.util.ArrayList$Itr.checkForComodification

2018 年 8 月 31 日

1、日志:

2018-04-13 20:00:55.757:WARN:oejs.ServletHandler:/g01-web/admin/activityManager/sendActivity.jsp
java.util.ConcurrentModificationException
	at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:859)
	at java.util.ArrayList$Itr.next(ArrayList.java:831)
	at org.apache.jsp.admin.activityManager.sendActivity_jsp._jspService(sendActivity_jsp.java:146)
	at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:111)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:848)
	at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:403)
	at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:492)
	at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:378)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:848)
	at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:684)
	at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:501)
	at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:137)
	at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:557)
	at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:231)
	at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1086)
	at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:428)
	at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:193)
	at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1020)
	at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:135)
	at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:116)
	at org.eclipse.jetty.server.Server.handle(Server.java:370)
	at org.eclipse.jetty.server.AbstractHttpConnection.handleRequest(AbstractHttpConnection.java:494)
	at org.eclipse.jetty.server.AbstractHttpConnection.content(AbstractHttpConnection.java:982)
	at org.eclipse.jetty.server.AbstractHttpConnection$RequestHandler.content(AbstractHttpConnection.java:1043)
	at org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:865)
	at org.eclipse.jetty.http.HttpParser.parseAvailable(HttpParser.java:240)
	at org.eclipse.jetty.server.AsyncHttpConnection.handle(AsyncHttpConnection.java:82)
	at org.eclipse.jetty.io.nio.SelectChannelEndPoint.handle(SelectChannelEndPoint.java:667)
	at org.eclipse.jetty.io.nio.SelectChannelEndPoint$1.run(SelectChannelEndPoint.java:52)
	at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:608)
	at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:543)
	at java.lang.Thread.run(Thread.java:745)

 

2、解决方法:


1)线程的 bug;
源码:
(在遍历对象时,同时修改对象的数据)

        for(ActivityInfo info : list){
            if(info.getActivityId() == Integer.parseInt(activityId)){
                System.out.println("del-info:"+info);
                list.removeinfo);
                accountService.notifyLogonPlayerActivity(ActivityNotifyType.FORCE_ACTIVITY.getCode(),info.getActivityId());
                break;
            } 
        }

 

2)修改:

        for(ActivityInfo info : list){
            if(info.getActivityId() == Integer.parseInt(activityId)){
                System.out.println("del-info:"+info);
                delActivity = info;
                accountService.notifyLogonPlayerActivity(ActivityNotifyType.FORCE_ACTIVITY.getCode(),info.getActivityId());
                break;
            } 
        }
        list.remove(delActivity); 

改为:跳出循环体后再修改对象。

 

3)foreach 的快速失败,

阿里巴巴 java 开发手册建议:


7. 【强制】不要在 foreach 循环里进行元素的 remove /add 操作。 remove 元素请使用 Iterator
方式,如果并发操作,需要对 Iterator 对象加锁。


 

flask+flask_sqlalchemy+flask_script+flask_migrate 创建一个flask项目(一)

flask+flask_sqlalchemy+flask_script+flask_migrate 创建一个flask项目(一)

最近开始学习flask, 做一下记录目前这个并不完善,后期会慢慢把这个项目该有的都搭建起来, 目前只是记录flask项目使用,有些详细的我可能也讲不出来,慢慢会去维护补充。如果时间充足,会用我的思路去做一个项目练习。

文件名可能不太规范。

 

1. 文件结构

 

  • 静态文件的默认文件夹:static
  • 静态文件的默认访问前缀:/static
  • 模板文件的默认文件夹:templates
testWeb # 项目文件
---- app # 主目录
  ---- model # 模型问价夹
    ---- user.py # 用户模型
  ---- dash.py # app 创建函数文件
  ---- handlers.py # 逻辑函数文件, 相当于djano 的 view
  ---- index.py # 没用,忘记删了
  ---- myRoutes.py # 路由文件
  ---- test.py # 没用忘记删了
---- config # 配置文件
  ---- __init__.py # 主配置写在这里
---- migrations # 使用manage 管理项目的时候自己创建的,主要记录数据迁移版本
---- static # 静态文件
---- templates # html
---- manage.py # 项目管理文件, 使其像diango的 python manage.py 一样使用

2. config.py 文件内容

DIALECT = 'MysqL' # 使用MysqL
DRIVER = 'pyMysqL' # 使用 pyMysqL 连接数据库
USERNAME = 'root' # 用户名
PASSWORD = '295213' # 密码
HOST = 'localhost' # ip
PORT = '3306' # 端口
DATABASE = 'hr' # 数据库名

# 数据库连接配置
sqlALCHEMY_DATABASE_URI = "{}+{}://{}:{}@{}:{}/{}?charset=utf8".format(
    DIALECT, DRIVER, USERNAME, PASSWORD, HOST, PORT, DATABASE
)
sqlALCHEMY_TRACK_MODIFICATIONS = False

注意: 数据库 hr 必须线创建。

2.  dash.py 文件内容及注释

from flask import Flask
from flask_cors import CORS
from flask_sqlalchemy import sqlAlchemy

import config    # 因为config配置是直接写在__init__ 中的所以直接导入即可

# 创建db
db = sqlAlchemy()
# 取消跨域请求问题

def create_app():
    # 创建app
    app = Flask(__name__)
    # 导入配置文件
    app.config.from_object(config)
    # 解决跨域请求问题
    CORS(app, resources=r'/*')
    # 数据库绑定app
    db.init_app(app)
    # 导入路由
    from . import myRoutes
    # 注册路由
    myRoutes.register(app)
    return app
View Code

3.  user.py  数据库表

from app.dash import db 

class Users(db.Model):
    __tablename__ = "users" # 创建时候的表名
    username = db.Column(db.VARCHAR(200), primary_key=True, comment="用户名")

    def __init__(self, username):
        self.username = username
View Code

4. handlers.py  逻辑处理

from app.model.user import Users

def index():
    users =  Users.query.filter()
    print(users)
    return users.first().username
View Code

 

flask_sqlalchemy model序列化

flask_sqlalchemy model序列化

import datetime


class SerializrAbleMixin(object):
"""A sqlAlchemy mixin class that can serialize itself as a JSON object"""
# args 自定义序列化字段 is_except 序列化是否排除字段 is_hump 返回是否用驼峰命名
def to_dict(self, *args, is_except=False, is_hump=False):
"""
序列化
:param args: 自定义序列化字段
:param is_except: 序列化是否根据args排除字段
:param is_hump: 返回是否用驼峰命名
:return: dict
"""
value = dict()
for column in self.__table__.columns:
attribute = getattr(self, column.name)
if isinstance(attribute, datetime.datetime):
attribute = str(attribute)
if is_hump is True:
column_name = self.__hump(column.name)
else:
column_name = column.name
if not args:
value[column_name] = attribute
else:
if is_except is False:
if column.name in args:
value[column_name] = attribute
else:
if column.name not in args:
value[column_name] = attribute
return value

def from_dict(self, attributes):
"""Update the current instance base on attribute->value by *attributes*"""
for attribute in attributes:
setattr(self, attribute, attributes[attribute])
return self

def __hump(self, column_name):
column_list = column_name.split('_')
for key in range(len(column_list)):
if key != 0:
column_list[key] = column_list[key].capitalize()
return ''.join(column_list)
使用
class ClassName(db.Model, SerializrAbleMixin):

flask_sqlalchemy 查询结果转dict 终极解决方案

flask_sqlalchemy 查询结果转dict 终极解决方案

  之前为了学习Python,试着拿Flask作框架搞小网站,感觉还不错,基本就抛弃了PHP。前段时间做了一个微信小程序,想着yii框架拿来写几十个小接口是不是浪费了,就继续用flask写api了,哪想到填坑无数啊。

  Python的ORM框架就属Sqlalchemy牛逼,网上资料也多,想着和yii里面应该差不多,就拿来用了。第二天万万没想到,php里面简单的一句asArray就能解决的问题,flask_sqlalchemy居然没有解决方案,查询的结果对象无法直接JSON序列化。这期间从南到北地找,大部分解决方案都是做一个JSON.dumps的Encoder方法,来转化restult对象,无意中看见https://www.cnblogs.com/wancy86/p/6421792.html 这个帖子,说queryresult对象加入了json属性,欣喜万分,搞了一晚上也没找到这个方法。

  原文链接:https://www.cnblogs.com/eating-gourd/p/9997751.html

 


 

咳咳,正文:  

  网上的方法主要问题在于只能处理result对象或model对象之一,当查询某个表全部字段时,如

1 db.session.query(User).filter().all()

  其返回User这个类的对象列表,而查询某些字段或者多表连接时,如:

 1 db.session.query(User.UserID,User.UserName).filter().all() 

  其返回result对象的列表,这两种情况下,对象的属性不同,导致很多情况下只能适应一种返回。今天趁闲着没事,把两种情况的查询结果转dict作了一下整理,封装为一个queryToDict函数,并同时支持all()返回的列表和first()返回的单个对象结果:

from datetime import datetime as cdatetime #有时候会返回datatime类型
from datetime import date,time
from flask_sqlalchemy import Model
from sqlalchemy.orm.query import Query
from sqlalchemy import DateTime,Numeric,Date,Time #有时又是DateTime

def queryToDict(models):
    if(isinstance(models,list)):
        if(isinstance(models[0],Model)):
            lst = []
            for model in models:
                gen = model_to_dict(model)
                dit = dict((g[0],g[1]) for g in gen)
                lst.append(dit)
            return lst
        else:
            res = result_to_dict(models)
            return res
    else:
        if (isinstance(models, Model)):
            gen = model_to_dict(models)
            dit = dict((g[0],g[1]) for g in gen)
            return dit
        else:
            res = dict(zip(models.keys(), models))
            find_datetime(res)
            return res
#当结果为result对象列表时,result有key()方法
def result_to_dict(results):
    res = [dict(zip(r.keys(), r)) for r in results]
    #这里r为一个字典,对象传递直接改变字典属性
    for r in res:
        find_datetime(r)
    return res
def model_to_dict(model):      #这段来自于参考资源
    for col in model.__table__.columns:
        if isinstance(col.type, DateTime):
            value = convert_datetime(getattr(model, col.name))
        elif isinstance(col.type, Numeric):
            value = float(getattr(model, col.name))
        else:
            value = getattr(model, col.name)
        yield (col.name, value)
def find_datetime(value):
    for v in value:
        if (isinstance(value[v], cdatetime)):
            value[v] = convert_datetime(value[v])   #这里原理类似,修改的字典对象,不用返回即可修改
def convert_datetime(value):
    if value:
        if(isinstance(value,(cdatetime,DateTime))):
            return value.strftime("%Y-%m-%d %H:%M:%S")
        elif(isinstance(value,(date,Date))):
            return value.strftime("%Y-%m-%d")
        elif(isinstance(value,(Time,time))):
            return value.strftime("%H:%M:%S")
    else:
        return ""
dit = dict((g[0],g[1]) for g in gen)相关代码也是之前查找资料获得,现在找不到出处了,作者可以联系我。
 滚去学雅思了,代码写得较快,欢迎指出bug

参考资源:

[1] https://stackoverflow.com/questions/5022066/how-to-serialize-sqlalchemy-result-to-json

[2] https://segmentfault.com/q/1010000007459402/a-1020000007460322

关于我如何知道是否可以禁用SQLALCHEMY_TRACK_MODIFICATIONS?怎么知道sql是否可以执行的介绍现已完结,谢谢您的耐心阅读,如果想了解更多关于FAQ(80):java.util.ConcurrentModificationException at java.util.ArrayList$Itr.checkForComodification、flask+flask_sqlalchemy+flask_script+flask_migrate 创建一个flask项目(一)、flask_sqlalchemy model序列化、flask_sqlalchemy 查询结果转dict 终极解决方案的相关知识,请在本站寻找。

本文标签: