84、flask之信号和mateclass元类

栏目: Python · 发布时间: 7年前

内容简介:84、flask之信号和mateclass元类

本篇导航:

  • flask实例化参数
  • 信号
  • metaclass元类解析

一、flask实例化参数

instance_path和instance_relative_config是配合来用的;

这两个参数是用来找配置文件的,当用app.config.from_pyfile('settings.py')这种方式导入配置文件的时候会用到

from flask import Flask,request
app = Flask(__name__,instance_path=None, instance_relative_config=True)
app.config.from_pyfile('settings.py') # C:\Users\Administrator\PycharmProjects\s6day120\1.实例化补充
# instsnce_path:#如果配置了instance_path,就会去找instance里面的文件
# instance_relative_config: #如果设置为True,配置文件就找不到了,就会去找instance里面的settings.py
app.open_session
print(app.config.get("NNN"))
@app.route('/index') # app.route('/index')  f(index)
def index():
    print(request)
    return "xx"

if __name__ == '__main__':
    app.__call__
    app.run()

如果设置了instance_releative_config = True,就找不着settings.py文件了,解决办法:就手动创建一个instance的文件夹

84、flask之信号和mateclass元类

二、信号(blinker)

1、flask的内置信号

Flask框架中的信号基于blinker,其主要就是让开发者可是在flask请求过程中定制一些用户行为。说白了也就是flask在列表里面

预留了几个空列表,在里面存东西。信号通过发送通知来帮助你解耦应用。简言之,信号允许某个发送者通知接收者有事情发生了;、

84、flask之信号和mateclass元类

10个信号:
 2. request_started = _signals.signal('request-started')                # 请求到来前执行
 5. request_finished = _signals.signal('request-finished')              # 请求结束后执行
                 
 3. before_render_template = _signals.signal('before-render-template')  # 模板渲染前执行
 4. template_rendered = _signals.signal('template-rendered')            # 模板渲染后执行
                 
 执行2/3/4/5或不执行时出现异常 got_request_exception = _signals.signal('got-request-exception')    # 请求执行出现异常时执行
                 
 6. request_tearing_down = _signals.signal('request-tearing-down')      # 请求执行完毕后自动执行(无论成功与否)
 7. appcontext_tearing_down = _signals.signal('appcontext-tearing-down')# 请求上下文执行完毕后自动执行(无论成功与否)
                 
                 
 1. appcontext_pushed = _signals.signal('appcontext-pushed')            # 请求app上下文push时执行
                
 8. appcontext_popped = _signals.signal('appcontext-popped')            # 请求上下文pop时执行
                
 message_flashed = _signals.signal('message-flashed')        # 调用flask在其中添加数据时,自动触发

1)问题1:

特殊的装饰器(@app.before_first_request ;@app.before_request ; @app.after_request)和信号有什么区别?

-  触发信号是没有返回值的,写不写返回值都无所谓

-  特殊的装饰器对返回值是有意义的,当before_request有返回值时就不会执行后续视图函数了,没有返回值的时候才会执行后续函数,而after_request必须有返回值所以特殊装饰器的功能比信号的功能强大

2)问题2:

通过信号可以做权限吗?

- 本身是做不了的,要想做得用其他的机制配合着来使用,这样做的话会闲的很麻烦,所以我们选择中间件来做

3)问题3:

信号用于做什么呢?

- 只做一些自定义的操作,而且没有返回值

- 降低代码之间的耦合

2、flask内置信号源码详细


from flask import Flask,render_template,flash
app = Flask(__name__)

@app.route('/index')
def index() :
    flash()
    return render_template()

if __name__ == '__main__':
    app.__call__
    app.run()

# 1 appcontext_pushed = _signals.signal('appcontext-pushed')  # 请求上下文push时执行
# def wsgi_app(self, environ, start_response):
#     def push(self):
#         def push(self):

# 2 request_started = _signals.signal('request-started')  # 请求到来前执行
# def wsgi_app(self, environ, start_response):
#     def full_dispatch_request(self):
#         request_started.send(self)

# 3 before_render_template = _signals.signal('before-render-template')  # 模板渲染前执行
# 4 template_rendered = _signals.signal('template-rendered')  # 模板渲染后执行
# def render_template(template_name_or_list, **context):
#     def _render(template, context, app):

# 5 request_finished = _signals.signal('request-finished')  # 请求结束后执行
# def wsgi_app(self, environ, start_response):
#     def full_dispatch_request(self):
#         def finalize_request(self, rv, from_error_handler=False):
#             request_finished.send(self, response=response)

# 2\3\4\5 哪里出错哪里执行都没出错不执行
# got_request_exception = _signals.signal('got-request-exception')  # 请求执行出现异常时执行
# def wsgi_app(self, environ, start_response):
#     def handle_exception(self, e):

# 6 request_tearing_down = _signals.signal('request-tearing-down')  # 请求执行完毕后自动执行(无论成功与否)
# def wsgi_app(self, environ, start_response):
#     def auto_pop(self, exc):
#         def pop(self, exc=_sentinel):
#             def do_teardown_request(self, exc=_sentinel):

# 7 appcontext_tearing_down = _signals.signal('appcontext-tearing-down')  # 请求上下文执行完毕后自动执行(无论成功与否)
# def wsgi_app(self, environ, start_response):
#     def auto_pop(self, exc):
#         def pop(self, exc=_sentinel):
#             # AppContext
#             def pop(self, exc=_sentinel):
#                 def do_teardown_appcontext(self, exc=_sentinel):

# 8 appcontext_popped = _signals.signal('appcontext-popped')  # 请求上下文pop时执行
# def wsgi_app(self, environ, start_response):
#     def auto_pop(self, exc):
#         def pop(self, exc=_sentinel):
#             # AppContext
#             def pop(self, exc=_sentinel):

# message_flashed = _signals.signal('message-flashed')  # 调用flask在其中添加数据时,自动触发
# def flash(message, category='message'):

View Code

三、metaclass元类解析

1、创建类的流程

84、flask之信号和mateclass元类

84、flask之信号和mateclass元类

2、什么是元类

Python 3中继承type的就是元类

元类示例

1)示例一


# 方式一
class MyType(type):
    '''继承type的就是元类'''
    def __init__(self,*args,**kwargs):
        print("MyType创建的对象",self)   #Foo
        super(MyType,self).__init__(*args,**kwargs)

    def __call__(self, *args, **kwargs):
        obj = super(MyType,self).__call__(*args,**kwargs)
        print("类创建对象",self,obj)   #Foo

class Foo(object,metaclass=MyType): #  对象加括号会去执行__call__方法,__call__方法里面继承了type的__call__方法
                                     ,type的__call__方法里面会先执行__new__方法,再去执行__init__方法。
                                      所以,Foo就是用type创建出来的
    user = "haiyan"
    age = 18

obj = Foo()

View Code

2)示例二


# 方式二
class MyType(type):
    def __init__(self, *args, **kwargs):
        print("ssss")
        super(MyType, self).__init__(*args, **kwargs)

    def __call__(cls, *args, **kwargs):
        v = dir(cls)
        obj = super(MyType, cls).__call__(*args, **kwargs)
        return obj
#对象加括号就会去执行__call__方法
class Foo(MyType('Zcc', (object,), {})):  #MyType('Zcc', (object,), {})相当于class Zcc(object):pass,也就是创建了一个Zcc的类
    user = 'haiyan'
    age = 18

obj = Foo()

View Code

3)示例三


# 方式三
class MyType(type):
    def __init__(self, *args, **kwargs):
        print("ssss")
        super(MyType, self).__init__(*args, **kwargs)

    def __call__(cls, *args, **kwargs):
        v = dir(cls)
        obj = super(MyType, cls).__call__(*args, **kwargs)
        return obj
#对象加括号就会去执行__call__方法

def with_metaclass(arg,base):
    print("类对象",MyType('Zcc', (base,), {}))
    return arg('Zcc', (base,), {})  #返回一个类对象  <class '__main__.Zcc'>

class Foo(with_metaclass(MyType,object)):  #MyType('Zcc', (object,), {})相当于class Zcc(object):pass,也就是创建了一个Zcc的类
    user = 'haiyan'
    age = 18

obj = Foo()

View Code

4)其他


class ASD(type):
    pass

qqq = ASD("qwe", (object,), {})  #用ASD这个元类创建了一个(qwe,并且继承object类的)类

# class ASD(qwe):
#     pass
obj = qqq()
# 能创建类的是元类
# 能创建对象的是类
print(obj)  #<__main__.qwe object at 0x00000000024FFBA8>
print(obj.__class__)  #<class '__main__.qwe'>
print(obj.__class__.__class__)  #<class '__main__.ASD'>
print(obj.__class__.__class__.__class__)  #<class 'type'>
print(obj.__class__.__class__.__class__.__class__)  #<class 'type'>

View Code

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Pro Git

Pro Git

Scott Chacon / Apress / 2009-8-27 / USD 34.99

Git is the version control system developed by Linus Torvalds for Linux kernel development. It took the open source world by storm since its inception in 2005, and is used by small development shops a......一起来看看 《Pro Git》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具