Flask系列之源码分析(一)
目录:
- 涉及知识点
- Flask框架原理
- 简单示例
- 路由系统原理源码分析
- 请求流程简单源码分析
- 响应流程简单源码分析
- session简单源码分析
涉及知识点
1、装饰器
闭包思想
- def wapper(func):
- def inner(*args,**kwargs):
- return func(*args,**kwargs)
- return inner
- """
- 1. 立即执行wapper函数,并将下面装饰的函数当做参数传递
- 2. 将wapper函数返回值获取,在index赋值
- index = inner函数
- """
- @wapper
- def index():
- print('函数内容')
- # 实际执行的 inner函数,inner函数内部调用原函数
- index()
ps.@functools.wraps,以上我们知道了python实现闭包,实际是index = inner(index)的封装思想。但不可避免的是inner封装后,会对封装的函数隐藏一些信息。如:包装异常,隐藏异常,打印日志,统计函数使用时间等。@functools.wraps通过update_wrapper函数,用参数wrapped表示的函数对象(例如:square)的一些属性(如:__name__、 __doc__)覆盖参数wrapper表示的函数对象(例如:callf,这里callf只是简单地调用square函数,因此可以说callf是 square的一个wrapper function)的这些相应属性。
- import functools
- def wapper(func):
- @functools.wraps(func)
- def inner(*args,**kwargs):
- return func(*args,**kwargs)
- return inner
- @wapper
- def index():
- print('函数内容')
- @wapper
- def order():
- print('函数内容')
- print(index.__name__)
- print(order.__name__)
2、面向对象封装
- class Foo(object):
- def __init__(self,age,name):
- self.age = age
- self.name = name
- class Bar(object):
- def __init__(self,counter):
- self.counter = counter
- self.obj = Foo('','石鹏')
- b1 = Bar(1)
- print(b1.obj.name)
3、python对象什么后面可以加括号
- - 函数
- 类
- 方法
- 对象
- def f1():
- print('f1')
- class F2(object):
- pass
- class F3(object):
- def __init__(self):
- pass
- def ff3(self):
- print('ff3')
- class F4(object):
- def __init__(self):
- pass
- def __call__(self, *args, **kwargs):
- print('f4')
- def func(arg):
- """
- 由于arg在函数中加括号,所以他只有4中表现形式:
- - 函数
- - 类
- - 方法
- - 对象
- :param arg:
- :return:
- """
- arg()
- # 1. 函数,内部执行函数
- func(f1)
- # 2. 类,内部执行__init__方法
- func(F2)
- # 3. 方法,obj.ff3
- obj1 = F3()
- func(obj1.ff3)
- # 4. 对象
- obj2 = F4()
- func(obj2)
4、call方法
- class F4(object):
- def __init__(self):
- print('构造方法')
- def __call__(self, *args, **kwargs):
- print('f4')
- def run(self,str1):
- print("run:%s" % str1)
- obj = F4()
- obj()
- obj.run('sssss')
5、函数和方法的区别
在于调用时有没有实例化对象,即跟某个对象关联。
- from types import MethodType,FunctionType
- class F3(object):
- def __init__(self):
- pass
- def ff3(self):
- print('ff3')
- #
- v1 = isinstance(F3.ff3,MethodType) # 方法
- v2 = isinstance(F3.ff3,FunctionType) # 函数
- print(v1,v2) # False,True
- obj = F3()
- v1 = isinstance(obj.ff3,MethodType) # 方法
- v2 = isinstance(obj.ff3,FunctionType) # 函数
- print(v1,v2) # True False
Flask框架原理
1、框架本质为通过socket模块实现工作流的请求和响应。
通过socket建立实例,accept等待请求地址,并通过编写路由系统来给予相应的响应。
- import socket
- def main():
- # 创建老师
- sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- sock.bind(('localhost', 8000))
- sock.listen(5)
- while True:
- # 老师等待 用户请求的到来
- connection, address = sock.accept()
- # 获取发送的内容:吴亦凡有没有女朋友?
- buf = connection.recv(1024)
- # 根据请求URL的不同:
- # 回答:没有
- connection.send(b"HTTP/1.1 200 OK\r\n\r\n")
- connection.send(b"No No No")
- # 关闭连接
- connection.close()
- if __name__ == '__main__':
- main()
2、flask通过werkzeug模块来帮助我们完成socket性能。
- """
- from werkzeug.wrappers import Request, Response
- from werkzeug.serving import run_simple
- @Request.application
- def hello(request):
- return Response('Hello World!')
- if __name__ == '__main__':
- # 当请求打来之后,自动执行:hello()
- run_simple('localhost', 4000, hello)
- """
- from werkzeug.wrappers import Request, Response
- from werkzeug.serving import run_simple
- class Foo(object):
- def __call__(self, *args, **kwargs):
- return Response('Hello World!')
- if __name__ == '__main__':
- # 当请求打来之后,自动执行:hello()
- obj = Foo()
- run_simple('localhost', 4000, obj)
3、flask快速入门
- """
- pip install flask
- pip3 install flask
- """
- from flask import Flask
- # 1. 实例化Flask对象
- app = Flask('xxxx')
- """
- 1. 执行 app.route('/index')并获取返回值 xx
- 2.
- @xx
- def index():
- return 'Hello World'
- 3. 执行 index = xx(index)
- 本质:
- {
- '/index': index
- }
- """
- @app.route('/index')
- def index():
- return 'Hello World'
- if __name__ == '__main__':
- app.run()
简单示例
1、实现简单登陆
- import functools
- from flask import Flask,render_template,request,redirect,session
- app = Flask('xxxx',template_folder="templates")
- app.secret_key = 'as923lrjks9d8fwlkxlduf'
- def auth(func):
- @functools.wraps(func)
- def inner(*args,**kwargs):
- user_info = session.get('user_info')
- if not user_info:
- return redirect('/login')
- return func(*args,**kwargs)
- return inner
- """
- {
- /order: inner函数, name: order
- /index: inner函数, name: index
- }
- """
- @app.route('/order',methods=['GET'])
- @auth
- def order():
- user_info = session.get('user_info')
- if not user_info:
- return redirect('/login')
- return render_template('index.html')
- @app.route('/index',methods=['GET'])
- @auth
- def index():
- return render_template('index.html')
- @app.route('/login',methods=['GET','POST'])
- def login():
- if request.method == "GET":
- return render_template('login.html')
- else:
- user = request.form.get('user')
- pwd = request.form.get('pwd')
- if user == 'alex' and pwd == '':
- session['user_info'] = user
- return redirect('/index')
- # return render_template('login.html',msg = "用户名或密码错误",x = 123)
- return render_template('login.html',**{'msg':'用户名或密码错误'})
- @app.route('/logout',methods=['GET'])
- def logout():
- del session['user_info']
- return redirect('/login')
- if __name__ == '__main__':
- app.run()
app.py
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>Title</title>
- </head>
- <body>
- <h1>登录页面</h1>
- <form method="post">
- <input type="text" name="user">
- <input type="password" name="pwd">
- <input type="submit" value="提交">{{msg}}
- </form>
- </body>
- </html>
templates/login.html
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>Title</title>
- </head>
- <body>
- <h1>欢迎进入系统</h1>
- <img src="/static/111.png" alt="">
- </body>
- </html>
templates/index.html
2、flask配置文件
- import functools
- from flask import Flask
- # 配置:模板/静态文件
- app = Flask('xxxx',template_folder="templates")
- # 配置:secret_key
- app.secret_key = 'as923lrjks9d8fwlkxlduf'
- # 导入配置文件
- app.config.from_object('settings.TestingConfig')
- @app.route('/index')
- def index():
- return "index"
- if __name__ == '__main__':
- app.run()
- class BaseConfig(object):
- DEBUG = False
- SESSION_REFRESH_EACH_REQUEST = True
- class ProConfig(BaseConfig):
- pass
- class DevConfig(BaseConfig):
- DEBUG = True
- class TestingConfig(BaseConfig):
- DEBUG = True
settings.py
ps.import importlib模块,模块支持传递字符串来导入模块。我们先来创建一些简单模块一遍演示。我们在模块里提供了相同接口,通过打印它们自身名字来区分。可通过importlib.import_module(module_path)来动态导入。其等价于import module_path。
路由系统原理源码分析
1、总体流程:
1.初始化Flask类,Rule类,Map类
2.调用app.route方法
3.route方法调用add_url_rule方法
4. add_url_rule方法rule = self.url_rule_class调用Rule方法,封装url和试图函数
5.add_url_rule方法调用url_map.add(Rule)对路由的rules进行添加[Rule('/index', 函数),]
6.map类存到self.url_map中,Rule存在url_rule_class中
- import functools
- from flask import Flask,views
- # 配置:模板/静态文件
- app = Flask('xxxx',template_folder="templates")
- """
- {
- '/index': index函数
- }
- 1. decorator = app.route('/index')
- 2.
- @decorator
- def index():
- return "index"
- 3. decorator(index)
- """
- """
- Map() = [
- Rule(rule=/index/ endpoint=None view_func=函数),
- ]
- """
- @app.route('/index')
- def index():
- return "index"
- """
- Map() = [
- Rule(rule=/index endpoint=None view_func=函数),
- Rule(rule=/order endpoint=None view_func=order),
- ]
- """
- def order():
- return 'Order'
- app.add_url_rule('/order', None, order)
- class TestView(views.View):
- methods = ['GET']
- def dispatch_request(self):
- return 'test!'
- app.add_url_rule('/test', view_func=TestView.as_view(name='test')) # name=endpoint
- # app.add_url_rule('/test', view_func=view函数) # name=endpoint
- def auth(func):
- def inner(*args, **kwargs):
- print('before')
- result = func(*args, **kwargs)
- print('after')
- return result
- return inner
- class X1View(views.MethodView):
- methods = ['GET','POST']
- decorators = [auth, ]
- def get(self):
- return 'x1.GET'
- def post(self):
- return 'x1.POST'
- app.add_url_rule('/x1', view_func=X1View.as_view(name='x1')) # name=endpoint
- if __name__ == '__main__':
- app.run()
2、初始化Flask类,Rule类,Map类
- #--------------------------------------
- # Flask类
- class Flask(_PackageBoundObject):
- url_rule_class = Rule
- def __init__(self, import_name, static_path=None, static_url_path=None,
- static_folder='static', template_folder='templates',
- instance_path=None, instance_relative_config=False,
- root_path=None)
- self.url_map = Map()
- #--------------------------------------
- # Role类
- @implements_to_string
- class Rule(RuleFactory):
- def __init__(self, string, defaults=None, subdomain=None, methods=None,
- build_only=False, endpoint=None, strict_slashes=None,
- redirect_to=None, alias=False, host=None):
- if not string.startswith('/'):
- raise ValueError('urls must start with a leading slash')
- self.rule = string
- self.is_leaf = not string.endswith('/')
- self.map = None
- self.strict_slashes = strict_slashes
- self.subdomain = subdomain
- self.host = host
- self.defaults = defaults
- self.build_only = build_only
- self.alias = alias
- if methods is None:
- self.methods = None
- else:
- if isinstance(methods, str):
- raise TypeError('param `methods` should be `Iterable[str]`, not `str`')
- self.methods = set([x.upper() for x in methods])
- if 'HEAD' not in self.methods and 'GET' in self.methods:
- self.methods.add('HEAD')
- self.endpoint = endpoint
- self.redirect_to = redirect_to
- if defaults:
- self.arguments = set(map(str, defaults))
- else:
- self.arguments = set()
- self._trace = self._converters = self._regex = self._weights = None
- #-------------------
- #map类
- class Map(object):
- default_converters = ImmutableDict(DEFAULT_CONVERTERS)
- def __init__(self, rules=None, default_subdomain='', charset='utf-8',
- strict_slashes=True, redirect_defaults=True,
- converters=None, sort_parameters=False, sort_key=None,
- encoding_errors='replace', host_matching=False):
- self._rules = []
- self._rules_by_endpoint = {}
- self._remap = True
- self._remap_lock = Lock()
- self.default_subdomain = default_subdomain
- self.charset = charset
- self.encoding_errors = encoding_errors
- self.strict_slashes = strict_slashes
- self.redirect_defaults = redirect_defaults
- self.host_matching = host_matching
- self.converters = self.default_converters.copy()
- if converters:
- self.converters.update(converters)
- self.sort_parameters = sort_parameters
- self.sort_key = sort_key
- for rulefactory in rules or ():
- self.add(rulefactory)
3、调用app.route方法
- def route(self, rule, **options):
- def decorator(f):
- endpoint = options.pop('endpoint', None)
- self.add_url_rule(rule, endpoint, f, **options)
- return f
- return decorator
4、route方法调用add_url_rule方法
- @setupmethod
- def add_url_rule(self, rule, endpoint=None, view_func=None, **options):
- if endpoint is None:
- endpoint = _endpoint_from_view_func(view_func)
- options['endpoint'] = endpoint
- methods = options.pop('methods', None)
- # if the methods are not given and the view_func object knows its
- # methods we can use that instead. If neither exists, we go with
- # a tuple of only ``GET`` as default.
- if methods is None:
- methods = getattr(view_func, 'methods', None) or ('GET',)
- if isinstance(methods, string_types):
- raise TypeError('Allowed methods have to be iterables of strings, '
- 'for example: @app.route(..., methods=["POST"])')
- methods = set(item.upper() for item in methods)
- # Methods that should always be added
- required_methods = set(getattr(view_func, 'required_methods', ()))
- # starting with Flask 0.8 the view_func object can disable and
- # force-enable the automatic options handling.
- provide_automatic_options = getattr(view_func,
- 'provide_automatic_options', None)
- if provide_automatic_options is None:
- if 'OPTIONS' not in methods:
- provide_automatic_options = True
- required_methods.add('OPTIONS')
- else:
- provide_automatic_options = False
- # Add the required methods now.
- methods |= required_methods
- rule = self.url_rule_class(rule, methods=methods, **options)
- rule.provide_automatic_options = provide_automatic_options
- self.url_map.add(rule)
5、 add_url_rule方法rule = self.url_rule_class调用Rule方法,封装url和试图函数
add_url_rule,代码同4 ;通过url_rule_class = Rule实例化,代码同2
6、add_url_rule方法调用url_map.add(Rule)对路由的rules进行添加[Rule('/index', 函数),]
add_url_rule代码同4,调用url_map.add方法
- def add(self, rulefactory):
- """Add a new rule or factory to the map and bind it. Requires that the
- rule is not bound to another map.
- :param rulefactory: a :class:`Rule` or :class:`RuleFactory`
- """
- for rule in rulefactory.get_rules(self):
- rule.bind(self)
- self._rules.append(rule)
- self._rules_by_endpoint.setdefault(rule.endpoint, []).append(rule)
- self._remap = True
7.map类存到self.url_map中,Rule存在url_rule_class中。
同代码2.
请求流程简单源码分析
1、综述:
1.已生成路由后,由app.run执行run方法
2.run方法通过werkzeug模块执行run_simple方法
3.werkzeug模块会触发__call__方法
4.__call__方法会触发wsgi_app
5.ctx=request_context对象,触发request_context对象
6.request_context对象__init__进行实例化
--request = app.request_class(environ)
7.flask初始化通过request实例化调用Request对象,通过request实例化调用Request对象
8.Request对象通过werkzeug模块__init__进行实例化
9.存储到ctx中
10.ctx.push()调用RequestContest.push方法
2、__call__方法会触发wsgi_app
- def __call__(self, environ, start_response):
- """Shortcut for :attr:`wsgi_app`."""
- return self.wsgi_app(environ, start_response)
3、ctx=request_context对象,触发request_context对象
- def wsgi_app(self, environ, start_response):
- ctx = self.request_context(environ)
- ctx.push()
4、request_context对象__init__进行实例化
- def request_context(self, environ):
- return RequestContext(self, environ)
--request = app.request_class(environ)
- def __init__(self, app, environ, request=None):
- self.app = app
- if request is None:
- request = app.request_class(environ)
- self.request = request
- self.url_adapter = app.create_url_adapter(self.request)
- self.flashes = None
- self.session = None
- # Request contexts can be pushed multiple times and interleaved with
- # other request contexts. Now only if the last level is popped we
- # get rid of them. Additionally if an application context is missing
- # one is created implicitly so for each level we add this information
- self._implicit_app_ctx_stack = []
- # indicator if the context was preserved. Next time another context
- # is pushed the preserved context is popped.
- self.preserved = False
- # remembers the exception for pop if there is one in case the context
- # preservation kicks in.
- self._preserved_exc = None
- # Functions that should be executed after the request on the response
- # object. These will be called before the regular "after_request"
- # functions.
- self._after_request_functions = []
- self.match_request()
5、flask初始化通过request实例化调用Request对象,通过request实例化调用Request对象
- class Flask(_PackageBoundObject):
- request_class = Request
6、Request对象通过werkzeug模块__init__进行实例化
- class Request(RequestBase):
- #: The internal URL rule that matched the request. This can be
- #: useful to inspect which methods are allowed for the URL from
- #: a before/after handler (``request.url_rule.methods``) etc.
- #:
- #: .. versionadded:: 0.6
- url_rule = None
- #: A dict of view arguments that matched the request. If an exception
- #: happened when matching, this will be ``None``.
- view_args = None
- #: If matching the URL failed, this is the exception that will be
- #: raised / was raised as part of the request handling. This is
- #: usually a :exc:`~werkzeug.exceptions.NotFound` exception or
- #: something similar.
- routing_exception = None
- # Switched by the request context until 1.0 to opt in deprecated
- # module functionality.
- _is_old_module = False
7、.存储到ctx中
同3代码
8、ctx.push()调用RequestContest.push方法
同3代码
flask的sesstion流程
1、综述
1.RequestContext.push,调用app.open_sesstion
2.self.session调用app.open_session
3.通过session_interface变量调用到secureCookieSeeionInerface类的open_session
4.如果没有,则session_class = SecureCookieSession,open_session经过loads加密返回self.session_class(),
5.将加密session返回到self.session
6.执行视图函数
response = self.full_dispatch_request()
----调用try_trigger_before_first_request_functions
(before_first_request)
----调用preprocess_request(before_request)
----调用dispatch_request(执行试图函数)
----调用finalize_request(@fater_request)
7.finalize_request
----response = self.process_response(response)
8.process_response
----执行@fater_request函数
----self.save_session(ctx.session, response)
9.通过self.save_session调用save_session并返回SecureCookieSessionInterface.save_session(self, session, response)
10.save_session保存session,报错return null
2、RequestContext.push,调用app.open_sesstion
- def wsgi_app(self, environ, start_response):
- ctx = self.request_context(environ)
- ctx.push()
- error = None
- try:
- try:
- # 4 执行视图函数
- response = self.full_dispatch_request()
- except Exception as e:
- # 异常处理试图报错,包含信号2345报错执行,got_request_exception信号
- error = e
- response = self.handle_exception(e)
- except:
- error = sys.exc_info()[1]
- raise
- # 将处理的内容,返回给用户浏览器
- return response(environ, start_response)
- finally:
- if self.should_ignore_error(error):
- error = None
- # 9、结束
- ctx.auto_pop(error)
通过self.session = self.app.open_session(self.request)调用flask.open_session方法
- def open_session(self, request):
- return self.session_interface.open_session(self, request)
3、self.session调用app.open_session
- class RequestContext(object):
- def push(self):
- self.session = self.app.open_session(self.request)
- if self.session is None:
- self.session = self.app.make_null_session()
4、通过session_interface变量调用到secureCookieSeeionInerface类的open_session
- class Flask(_PackageBoundObject):
- session_interface = SecureCookieSessionInterface()
5、如果没有,则session_class = SecureCookieSession,open_session经过loads加密返回self.session_class(),
- class SecureCookieSessionInterface(SessionInterface):
- """The default session interface that stores sessions in signed cookies
- through the :mod:`itsdangerous` module.
- """
- #: the salt that should be applied on top of the secret key for the
- #: signing of cookie based sessions.
- salt = 'cookie-session'
- #: the hash function to use for the signature. The default is sha1
- digest_method = staticmethod(hashlib.sha1)
- #: the name of the itsdangerous supported key derivation. The default
- #: is hmac.
- key_derivation = 'hmac'
- #: A python serializer for the payload. The default is a compact
- #: JSON derived serializer with support for some extra Python types
- #: such as datetime objects or tuples.
- serializer = session_json_serializer
- session_class = SecureCookieSession
- def open_session(self, app, request):
# sission,key值
s = self.get_signing_serializer(app)
if s is None:
return None
# 如果能从cookie拿到session的话
val = request.cookies.get(app.session_cookie_name)
if not val:
return self.session_class() #如果没有session,则返回一个空字典
max_age = total_seconds(app.permanent_session_lifetime)
try:
data = s.loads(val, max_age=max_age) # 加密保存
return self.session_class(data)
except BadSignature:
return self.session_class() # 返回session类
6、将加密session返回到self.session
- class RequestContext(object):
- def push(self):
- self.session = self.app.open_session(self.request)
- if self.session is None:
- self.session = self.app.make_null_session()
7、执行视图函数
response = self.full_dispatch_request()
同代码2
----调用try_trigger_before_first_request_functions
(before_first_request)
- def full_dispatch_request(self):
- """Dispatches the request and on top of that performs request
- pre and postprocessing as well as HTTP exception catching and
- error handling.
- .. versionadded:: 0.7
- """
- # 触发只执行一次的装饰器函数,@before_first_request
- self.try_trigger_before_first_request_functions()
----调用preprocess_request(before_request)
----调用dispatch_request(执行试图函数)
----调用finalize_request(@fater_request)
- def full_dispatch_request(self):
- try:
- # 执行特殊装饰器:before_request装饰的所有函数
- # 如果没有返回值,rv=None;有返回值 “嘻嘻嘻”
- rv = self.preprocess_request()
- if rv is None:
- # 触发执行视图函数,使用session
- rv = self.dispatch_request()
- except Exception as e:
- rv = self.handle_user_exception(e)
- # 6 对返回值进行封装,执行@fater_request装饰器;session保存
- return self.finalize_request(rv)
8、finalize_request
----response = self.process_response(response)
- def finalize_request(self, rv, from_error_handler=False):
- ''' 创建返视图返回'''
- response = self.make_response(rv)
- try:
- '''返回值'''
- response = self.process_response(response)
- # 执行信号request_finished
- request_finished.send(self, response=response)
- except Exception:
- if not from_error_handler:
- raise
- self.logger.exception('Request finalizing failed with an '
- 'error while handling an error')
- return response
9、process_response
----执行@fater_request函数
----self.save_session(ctx.session, response)
- def process_response(self, response):
- ctx = _request_ctx_stack.top
- bp = ctx.request.blueprint
- funcs = ctx._after_request_functions
- if bp is not None and bp in self.after_request_funcs:
- funcs = chain(funcs, reversed(self.after_request_funcs[bp]))
- if None in self.after_request_funcs:
- funcs = chain(funcs, reversed(self.after_request_funcs[None]))
- # 执行 after_request装饰器
- for handler in funcs:
- response = handler(response)
- # 将内存中的session持久化到:数据库、....
- if not self.session_interface.is_null_session(ctx.session):
- self.save_session(ctx.session, response)
- return response
10、通过self.save_session调用save_session并返回SecureCookieSessionInterface.save_session(self, session, response)
- # Flask类
def save_session(self, session, response):- return self.session_interface.save_session(self, session, response)
11、save_session保存session,报错return null
- SecureCookieSessionInterface类:
- def save_session(self, app, session, response):
- domain = self.get_cookie_domain(app) # 域名
- path = self.get_cookie_path(app) # 路径
- # Delete case. If there is no session we bail early.
- # If the session was modified to be empty we remove the
- # whole cookie.
- if not session:
- if session.modified:
- response.delete_cookie(app.session_cookie_name,
- domain=domain, path=path)
- return
- # Modification case. There are upsides and downsides to
- # emitting a set-cookie header each request. The behavior
- # is controlled by the :meth:`should_set_cookie` method
- # which performs a quick check to figure out if the cookie
- # should be set or not. This is controlled by the
- # SESSION_REFRESH_EACH_REQUEST config flag as well as
- # the permanent flag on the session itself.
- if not self.should_set_cookie(app, session):
- return
- httponly = self.get_cookie_httponly(app)
- secure = self.get_cookie_secure(app)
- expires = self.get_expiration_time(app, session)
- val = self.get_signing_serializer(app).dumps(dict(session)) # 加密
- response.set_cookie(app.session_cookie_name, val, # 最后保存在cookie中
- expires=expires, httponly=httponly,
- domain=domain, path=path, secure=secure)
附录
Flask系列之源码分析(一)的更多相关文章
- Flask系列之源码分析(二)
应用技术点 python之__setattr__ python之threading.local python之偏函数 flask源码上下文管理 1.综述过程 将请求对象压入栈 1.请求进入 __cal ...
- Spring基础系列-AOP源码分析
原创作品,可以转载,但是请标注出处地址:https://www.cnblogs.com/V1haoge/p/9560803.html 一.概述 Spring的两大特性:IOC和AOP. AOP是面向切 ...
- flask/app.py-add_url_rule源码分析
之前分析route方法的时候,可以看到中间会调用add_url_rule方法,add_url_rule方法和route方法一样属于Flask这个类的. add_url_rule方法主要用来连接url规 ...
- Tomcat详解系列(3) - 源码分析准备和分析入口
Tomcat - 源码分析准备和分析入口 上文我们介绍了Tomcat的架构设计,接下来我们便可以下载源码以及寻找源码入口了.@pdai 源代码下载和编译 首先是去官网下载Tomcat的源代码和二进制安 ...
- Flask之wtforms源码分析
一.wtforms源码流程 1.实例化流程分析 # 源码流程 1. 执行type的 __call__ 方法,读取字段到静态字段 cls._unbound_fields 中: meta类读取到cls._ ...
- Kafka源码系列之源码分析zookeeper在kafka的作用
浪尖的kafka源码系列以kafka0.8.2.2源码为例给大家进行讲解的.纯属个人爱好,希望大家对不足之处批评指正. 一,zookeeper在分布式集群的作用 1,数据发布与订阅(配置中心) 发布与 ...
- Android进阶系列之源码分析Activity的启动流程
美女镇楼,辟邪! 源码,是一个程序猿前进路上一个大的而又不得不去翻越障碍,我讨厌源码,看着一大堆.5000多行,要看完得啥时候去了啊.不过做安卓的总有这一天,自从踏上这条不归路,我就认命了.好吧,我慢 ...
- flask请求上下文源码分析
一.什么是上下文 每一段程序都有很多外部变量,只有像add这种简单的函数才是没有外部变量的,一旦你的一段程序有了外部变量,这段程序就不完整了,不能独立运行,你为了使他们能运行,就要给所有的外部变量一个 ...
- Spring IOC 容器源码分析系列文章导读
1. 简介 Spring 是一个轻量级的企业级应用开发框架,于 2004 年由 Rod Johnson 发布了 1.0 版本.经过十几年的迭代,现在的 Spring 框架已经非常成熟了.Spring ...
随机推荐
- 浅析Linux内核同步机制
非常早之前就接触过同步这个概念了,可是一直都非常模糊.没有深入地学习了解过,最近有时间了,就花时间研习了一下<linux内核标准教程>和<深入linux设备驱动程序内核机制>这 ...
- Mac普通用户修改了/etc/sudoers文件的解决办法
1.开启 Root 账户 打开“系统偏好设置”,进入“用户与群组”面板,记得把面板左下角的小锁打开,然后选择面板里的“登录选项”.在面板右边你会看到“网络账户服务 器”,点击它旁边的“加入…”按钮,再 ...
- 【RF库Collections测试】Count Values In List
Name:Count Values In ListSource:Collections <test library>Arguments:[ list_ | value | start=0 ...
- linux系统socket通信编程2
一.概述 TCP(传输控制协议)和UDP(用户数据报协议是网络体系结构TCP/IP模型中传输层一层中的两个不同的通信协议. TCP:传输控制协议,一种面向连接的协议,给用户进程提供可靠的全双工的字节流 ...
- linux系统usb挂载
本次例程的环境是在FC6下,通过终端操作的. 注意要挂载U盘需要有管理员的权限. 切换成管理员,输入: su root 然后输入管理员密码,进行密码认证: 成功后,先在 /mnt 下建立一个名叫USB ...
- cocos2dx游戏--欢欢英雄传说--添加血条
用一个空血槽图片的Sprite做背景,上面放一个ProgressTimer, 通过设置ProgressTimer的进度来控制血条的长短.建立一个Progress类来实现.Progress.h: #if ...
- Android AndroidManifest.xml配置文件
AndroidManifest.xml配置文件介绍本质:AndroidManifest.xml是整个应用的主配置清单文件.包含:该应用的包名.版本号.组件.权限等信息.作用:记录该应用的相关配置信息. ...
- php第一例
参考 例子 https://www.cnblogs.com/chinajins/p/5622342.html 配置多个网站 https://blog.csdn.net/win7system/artic ...
- js offset
1.offsetParent offsetParent属性返回一个对象的引用,这个对象是距离调用offsetParent的元素最近的(在包含层次中最靠近的),并且是已进行过CSS定位的容器元素. 如果 ...
- gradle下的第一个SpringMVC应用
新建gradle project 缺少了很多文件夹和文件,我们自己补充,补充完的目录如下: HelloController: package controller; import javax.serv ...