老年手机总出现正在查找我的iphone关机了关机一下在开机就好

  来源:fanchunke1991
  /a/2550
  相信很多初学Flask的同学(包括我自己),在阅读官方文档或者Flask的学习资料时,对于它的认识是从以下的一段代码开始的:
  from flask import Flask
  app= Flask(__name__)
  @app.route('/')
  def index():
  return"Hello World!"
  if__name__== '__main__':
  app.run()
  运行如上代码,在浏览器中访问http://localhost:5000/,便可以看到Hello World!出现了。这是一个很简单的Flask的应用。
  然而,这段代码怎么运行起来的呢?一个Flask应用运转的背后又有哪些逻辑呢?如果你只关心Web应用,那对这些问题不关注也可以,但从整个Web编程的角度来看,这些问题非常有意义。本文就主要针对一个Flask应用的运行过程进行简要分析,后续文章还会对Flask框架的一些具体问题进行分析。
  为了分析方便,本文采用 Flask 0.1版本 的源码进行相关问题的探索。
  一些准备知识
  在正式分析Flask之前,有一些准备知识需要先了解一下:
使用Flask框架开发的属于Web应用。由于Python使用WSGI网关,所以这个应用也可以叫WSGI应用;
服务器、Web应用的设计应该遵循网关接口的一些规范。对于WSGI网关,要求Web应用实现一个函数或者一个可调用对象webapp(environ, start_response)。服务器或网关中要定义start_response函数并且调用Web应用。关于这部分的内容可以参考:wsgiref包——符合WSGI标准的Web服务实现(一)。
Flask依赖于底层库werkzeug。相关内容可以参考:Werkzeug库简介。
  本文暂时不对服务器或网关的具体内容进行介绍,只需对服务器、网关、Web应用之间有怎样的关系,以及它们之间如何调用有一个了解即可。
  一个Flask应用运行的过程
  1. 实例化一个Flask应用
  使用app = Flask(__name__),可以实例化一个Flask应用。实例化的Flask应用有一些要点或特性需要注意一下:
  1.对于请求和响应的处理,Flask使用werkzeug库中的Request类和Response类。对于这两个类的相关内容可以参考:Werkzeug库——wrappers模块。
  对于URL模式的处理,Flask应用使用werkzeug库中的Map类和Rule类,每一个2. URL模式对应一个Rule实例,这些Rule实例最终会作为参数传递给Map类构造包含所有URL模式的一个“地图”。这个地图可以用来匹配请求中的URL信息,关于Map类和Rule类的相关知识可以参考:Werkzeug库——routing模块。
  3. 当实例化一个Flask应用app(这个应用的名字可以随便定义)之后,对于如何添加URL模式,Flask采取了一种更加优雅的模式,对于这点可以和Django的做法进行比较。Flask采取装饰器的方法,将URL规则和视图函数结合在一起写,其中主要的函数是route。在上面例子中:
  @app.route('/')
  def index():
  这样写视图函数,会将'/'这条URL规则和视图函数index()联系起来,并且会形成一个Rule实例,再添加进Map实例中去。当访问'/'时,会执行index()。关于Flask匹配URL的内容,可以参考后续文章。
  4. 实例化Flask应用时,会创造一个Jinja环境,这是Flask自带的一种模板引擎。可以查看Jinja文档,这里先暂时不做相关介绍。
  5. 实例化的Flask应用是一个可调用对象。在前面讲到,Web应用要遵循WSGI规范,就要实现一个函数或者一个可调用对象webapp(environ, start_response),以方便服务器或网关调用。Flask应用通过__call__(environ, start_response)方法可以让它被服务器或网关调用。
  def __call__(self,environ,start_response):
  """Shortcut for :attr:`wsgi_app`"""
  returnself.wsgi_app(environ,start_response)
  注意到调用该方法会执行wsgi_app(environ, start_response)方法,之所以这样设计是为了在应用正式处理请求之前,可以加载一些“中间件”,以此改变Flask应用的相关特性。对于这一点后续会详细分析。
  6. Flask应用还有一些其他的属性或方法,用于整个请求和响应过程。
  2.调用Flask应用时会发生什么
  上面部分分析了实例化的Flask应用长什么样子。当一个完整的Flask应用实例化后,可以通过调用app.run()方法运行这个应用。
  Flask应用的run()方法会调用werkzeug.serving模块中的run_simple方法。这个方法会创建一个本地的测试服务器,并且在这个服务器中运行Flask应用。关于服务器的创建这里不做说明,可以查看werkzeug.serving模块的有关文档。
  当服务器开始调用Flask应用后,便会触发Flask应用的__call__(environ, start_response)方法。其中environ由服务器产生,start_response在服务器中定义。
  上面我们分析到当Flask应用被调用时会执行wsgi_app(environ, start_response)方法。可以看出,wsgi_app是真正被调用的WSGI应用,之所以这样设计,就是为了在应用正式处理请求之前,wsgi_app可以被一些“中间件”装饰,以便先行处理一些操作。为了便于理解,这里先举两个例子进行说明。
  例子一: 中间件SharedDataMiddleware
  中间件SharedDataMiddleware是werkzeug.wsgi模块中的一个类。该类可以为Web应用提供静态内容的支持。例如:
  import os
  from werkzeug.wsgi import SharedDataMiddleware
  app= SharedDataMiddleware(app,{
  '/shared': os.path.join(os.path.dirname(__file__),'shared')
  Flask应用通过以上的代码,app便会成为一个SharedDataMiddleware实例,之后便可以在/shared/中访问shared文件夹下的内容。
  对于中间件SharedDataMiddleware,Flask应用在初始实例化的时候便有所应用。其中有这样一段代码:
  self.wsgi_app= SharedDataMiddleware(self.wsgi_app,{
  self.static_path: target
  这段代码显然会将wsgi_app变成一个SharedDataMiddleware对象,这个对象为Flask应用提供一个静态文件夹/static。这样,当整个Flask应用被调用时,self.wsgi_app(environ, start_response)会执行。由于此时self.wsgi_app是一个SharedDataMiddleware对象,所以会先触发SharedDataMiddleware对象的__call__(environ, start_response)方法。如果此时的请示是要访问/static这个文件夹,SharedDataMiddleware对象会直接返回响应;如果不是,则才会调用Flask应用的wsgi_app(environ.start_response)方法继续处理请求。
  例子二: 中间件DispatcherMiddleware
  中间件DispatcherMiddleware也是werkzeug.wsgi模块中的一个类。这个类可以讲不同的应用“合并”起来。以下是一个使用中间件DispatcherMiddleware的例子。
  from flask import Flask
  from werkzeug import DispatcherMiddleware
  app1= Flask(__name__)
  app2= Flask(__name__)
  app= Flask(__name__)
  @app1.route('/')
  def index():
  return"This is app1!"
  @app2.route('/')
  def index():
  return"This is app2!"
  @app.route('/')
  def index():
  return"This is app!"
  app= DispatcherMiddleware(app,{
  '/app1': app1,
  '/app2': app2
  if__name__== '__main__':
  from werkzeug.serving import run_simple
  run_simple('localhost',5000,app)
  在上面的例子中,我们首先创建了三个不同的Flask应用,并为每个应用创建了一个视图函数。但是,我们使用了DispatcherMiddleware,将app1、app2和app合并起来。这样,此时的app便成为一个DispatcherMiddleware对象。
  当在服务器中调用app时,由于它是一个DispatcherMiddleware对象,所以首先会触发它的__call__(environ, start_response)方法。然后根据请求URL中的信息来确定要调用哪个应用。例如:
如果访问/,则会触发app(environ, start_response)(注意: 此时app是一个Flask对象),进而处理要访问app的请求;
如果访问/app1,则会触发app1(environ, start_response),进而处理要访问app1的请求。访问/app2同理。
  3. 和请求处理相关的上下文对象
  当Flask应用真正处理请求时,wsgi_app(environ, start_response)被调用。这个函数是按照下面的方式运行的:
  def wsgi_app(environ,start_response):
  with self.request_context(environ):
  请求上下文
  可以看到,当Flask应用处理一个请求时,会构造一个上下文对象。所有的请求处理过程,都会在这个上下文对象中进行。这个上下文对象是_RequestContext类的实例。
  # Flask v0.1
  class_RequestContext(object):
  """The request context contains all request relevant information. It is
  created at the beginning of the request and pushed to the
  `_request_ctx_stack` and removed at the end of it. It will create the
  URL adapter and request object for the WSGI environment provided.
  def __init__(self,app,environ):
  self.app= app
  self.url_adapter= app.url_map.bind_to_environ(environ)
  self.request= app.request_class(environ)
  self.session= app.open_session(self.request)
  self.g= _RequestGlobals()
  self.flashes= None
  def __enter__(self):
  _request_ctx_stack.push(self)
  def __exit__(self,exc_type,exc_value,tb):
  # do not pop the request stack if we are in debug mode and an
  # exception happened. This will allow the debugger to still
  # access the request object in the interactive shell.
  iftb isNone ornotself.app.debug:
  _request_ctx_stack.pop()
  根据_RequestContext上下文对象的定义,可以发现,在构造这个对象的时候添加了和Flask应用相关的一些属性:
app ——上下文对象的app属性是当前的Flask应用;
url_adapter ——上下文对象的url_adapter属性是通过Flask应用中的Map实例构造成一个MapAdapter实例,主要功能是将请求中的URL和Map实例中的URL规则进行匹配;
request ——上下文对象的request属性是通过Request类构造的实例,反映请求的信息;
session ——上下文对象的session属性存储请求的会话信息;
g ——上下文对象的g属性可以存储全局的一些变量。
flashes ——消息闪现的信息。
  LocalStack和一些“全局变量”
  注意: 当进入这个上下文对象时,会触发_request_ctx_stack.push(self)。在这里需要注意Flask中使用了werkzeug库中定义的一种数据结构LocalStack。
  _request_ctx_stack = LocalStack()
  关于LocalStack,可以参考:Werkzeug库——local模块。LocalStack是一种栈结构,每当处理一个请求时,请求上下文对象_RequestContext会被放入这个栈结构中。数据在栈中存储的形式表现成如下:
  {880: {'stack': [&flask._RequestContext object&]}, 13232: {'stack': [&flask._RequestContext object&]}}
  这是一个字典形式的结构,键代表当前线程/协程的标识数值,值代表当前线程/协程存储的变量。werkzeug.local模块构造的这种结构,很容易实现线程/协程的分离。也正是这种特性,使得可以在Flask中访问以下的“全局变量”:
  current_app= LocalProxy(lambda: _request_ctx_stack.top.app)
  request= LocalProxy(lambda: _request_ctx_stack.top.request)
  session= LocalProxy(lambda: _request_ctx_stack.top.session)
  g= LocalProxy(lambda: _request_ctx_stack.top.g)
  其中_request_ctx_stack.top始终指向当前线程/协程中存储的“请求上下文”,这样像app、request、session、g等都可以以“全局”的形式存在。这里“全局”是指在当前线程或协程当中。
  由此可以看出,当处理请求时:
首先,会生成一个请求上下文对象,这个上下文对象包含请求相关的信息。并且在进入上下文环境时,LocalStack会将这个上下文对象推入栈结构中以存储这个对象;
在这个上下文环境中可以进行请求处理过程,这个稍后再介绍。不过可以以一种“全局”的方式访问上下文对象中的变量,例如app、request、session、g等;
当请求结束,退出上下文环境时,LocalStack会清理当前线程/协程产生的数据(请求上下文对象);
Flask 0.1版本只有“请求上下文”的概念,在Flask 0.9版本中又增加了“应用上下文”的概念。关于“应用上下文”,以后再加以分析。
  4. 在上下文环境中处理请求
  处理请求的过程定义在wsgi_app方法中,具体如下:
  def wsgi_app(environ,start_response):
  with self.request_context(environ):
  rv= self.preprocess_request()
  ifrv isNone:
  rv= self.dispatch_request()
  response= self.make_response(rv)
  response= self.process_response(response)
  returnresponse(environ,start_response)
  从代码可以看出,在上下文对象中处理请求的过程分为以下几个步骤:
在请求正式被处理之前的一些操作,调用preprocess_request()方法,例如打开一个数据库连接等操作;
正式处理请求。这个过程调用dispatch_request()方法,这个方法会根据URL匹配的情况调用相关的视图函数;
将从视图函数返回的值转变为一个Response对象;
在响应被发送到WSGI服务器之前,调用process_response(response)做一些后续处理过程;
调用response(environ, start_response)方法将响应发送回WSGI服务器。关于此方法的使用,可以参考:Werkzeug库——wrappers模块;
退出上下文环境时,LocalStack会清理当前线程/协程产生的数据(请求上下文对象)。
看完本文有收获?请转发分享给更多人
关注「Python开发者」,提升Python技能
声明:本文由入驻搜狐公众平台的作者撰写,除搜狐官方账号外,观点仅代表作者本人,不代表搜狐立场。3073人阅读
Network(22)
Flask(1)
之前对 Nginx,WSGI(或者 uWSGI,uwsgi),Flask(或者 Django),这几者的关系一存存在疑惑。通过查阅了些资料,总算把它们的关系理清了。
总括来说,客户端从发送一个 HTTP 请求到 Flask 处理请求,分别经过了 web服务器层,WSGI层,web框架层,这三个层次。不同的层次其作用也不同,下面简要介绍各层的作用。
图1:web服务器,web框架与 WSGI 的三层关系
Web服务器层
对于传统的客户端 - 服务器架构,其请求的处理过程是,客户端向服务器发送请求,服务器接收请求并处理请求,然后给客户端返回响应。在这个过程中,服务器的作用是:
Web服务器是一类特殊的服务器,其作用是主要是接收 HTTP 请求并返回响应。提起 web服务器大家都不会陌生,常见的 web服务器有 Nginx,Apache,IIS等。在上图1的三层结构中,web服务器是最先接收用户请求的,并将响应结果返回给用户。
Web框架的作用主要是方便我们开发 web应用程序,HTTP请求的动态数据就是由 web框架层来提供的。常见的 web框架有Flask,Django等,我们以 Flask 框架为例子,展示 web框架的作用:
from flask import Flask
app = Flask(__name__)
@app.route('/hello')
def hello_world():
return 'Hello World!'
if __name__ == '__main__':
app.run(host='0.0.0.0', port=8080)
以上简单的几行代码,就创建了一个 web应用程序对象 app。app 监听机器所有 ip 的 8080 端口,接受用户的请求连接。我们知道,HTTP 协议使用 URL 来定位资源,上面的程序会将路径 /hello 的请求交由 hello_world 方法处理,hello_world 返回 ‘Hello World!’ 字符串。对于 web框架的使用者来说,他们并不关心如何接收 HTTP 请求,也不关心如何将请求路由到具体方法处理并将响应结果返回给用户。Web框架的使用者在大部分情况下,只需要关心如何实现业务的逻辑即可。
WSGI 不是服务器,也不是用于与程序交互的API,更不是真实的代码,WSGI 只是一种接口,它只适用于 Python 语言,其全称为 Web Server Gateway Interface,定义了 web服务器和 web应用之间的接口规范。也就是说,只要 web服务器和 web应用都遵守WSGI协议,那么 web服务器和 web应用就可以随意的组合。
下面的代码展示了 web服务器是如何与 web应用组合在一起的。
def application(env, start_response):
start_response('200 OK', [('Content-Type', 'text/html')])
return [b"Hello World"]
方法 application由 web服务器调用,参数env,start_response 由 web服务器实现并传入。其中,env是一个字典,包含了类似 HTTP_HOST,HOST_USER_AGENT,SERVER_PROTOCO 等环境变量。start_response则是一个方法,该方法接受两个参数,分别是status,response_headers。application方法的主要作用是,设置 http 响应的状态码和 Content-Type 等头部信息,并返回响应的具体结果。
上述代码就是一个完整的 WSGI 应用,当一个支持 WSGI 的 web服务器接收到客户端的请求后,便会调用这个 application 方法。WSGI 层并不需要关心env,start_response 这两个变量是如何实现的,就像在 application 里面所做的,直接使用这两个变量即可。
值得指出的是,WSGI 是一种协议,需要区分几个相近的名词:
同 wsgi 一样也是一种协议,uWSGI服务器正是使用了 uwsgi 协议
实现了 uwsgi 和 WSGI 两种协议的web服务器。注意 uWSGI 本质上也是一种 web服务器,处于上面描述的三层结构中的 web服务器层。
通用网关接口,并不限于 Python 语言,定义了 web服务器是如何向客户端提供动态的内容。例如,规定了客户端如何将参数传递给 web服务器,web服务器如何将参数传递给 web应用,web应用如何将它的输出如何发送给客户端,等等。
生产环境下的 web应用都不使用 CGI 了,CGI进程(类似 Python 解释器)针对每个请求创建,用完就抛弃,效率低下。WSGI 正是为了替代 CGI 而出现的。
说到这,我们基本理清了 WSGI 在 web服务器与 web框架之间作用:WSGI 就像一条纽带,将 web服务器与 web框架连接起来。回到本文的题目,Nginx 属于一种 web服务器,Flask属于一种 web框架,因此,WSGI 与 Nginx、Flask 的作用就不明而喻了。
最后以 Nginx,WSGI,Flask 之间的对话结束本文。
Nginx:Hey,WSGI,我刚收到了一个请求,我需要你作些准备,然后由Flask来处理这个请求。
WSGI:OK,Nginx。我会设置好环境变量,然后将这个请求传递给Flask处理。
Flask:Thanks WSGI!给我一些时间,我将会把请求的响应返回给你。
WSGI:Alright,那我等你。
Flask:Okay,我完成了,这里是请求的响应结果,请求把结果传递给Nginx。
WSGI:Good job!Nginx,这里是响应结果,已经按照要求给你传递回来了。
Nginx:Cool,我收到了,我把响应结果返回给客户端。大家合作愉快~
参考资料:
《Python核心编程(第3版)》Wesley Chun著
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:396080次
积分:4775
积分:4775
排名:第5365名
原创:145篇
评论:87条
阅读:4261
阅读:4726
文章:53篇
阅读:54878
文章:17篇
阅读:139013
(1)(7)(10)(2)(7)(1)(1)(3)(3)(2)(4)(3)(1)(1)(2)(2)(3)(7)(3)(2)(1)(1)(1)(2)(1)(2)(1)(1)(1)(1)(1)(1)(1)(17)(6)(19)(16)(1)(2)(1)(1)(1)(1)(1)(1)(1)(1)(1)(2)(1)(1)zhangkechen 的BLOG
用户名:zhangkechen
访问量:1663
注册日期:
阅读量:5863
阅读量:12276
阅读量:416534
阅读量:1103979
51CTO推荐博文
& & &同事用flask写了一些代码,需要用apache跑起来。下面记录一下搭建的过程& && & &环境:ubuntu 12.04& & &1、安装相关包:& & &apt-get install&python-flask &libapache2-mod-wsgi& & &注: 原来flask是需要安装的。 (^_^!)& & & & & & &wsgi 是做什么的呢?& & &&WSGI&is a specification of a generic API for mapping between an underlying web server and a Python web application. WSGI itself is described by Python&. The purpose of the WSGI specification is to provide a common mechanism for hosting a Python web application on a range of different web servers supporting the Python programming language& & & WSGI 是介于webserver 和python web 应用之间的一通用性的规范接口,目的是提供一个通用的机制在不同的webserver 布 署python程序& &2、apache的配置:& & & 写一个比较简单的& &&&VirtualHost&*:80&
&&&&ServerName&&&
DocumentRoot&&/var/www/vpn/
&&&&WSGIScriptReloading&On
&&&&WSGIScriptAlias&/&/var/www/what/what.wsgi
&&&&&Directory&"/var/www/what/"&
&&&&&&&&Order&Deny,Allow
&&&&&&&&Allow&from&all
&&&&&/Directory&
&/VirtualHost&& & 注: 这里要写一个what.wsgi的文件文件内容也比较简单
import&sys
sys.path.insert(0,&'/var/www/what/')
from&&index&import&app&as&application前两行如果说what.wsgi跟脚本们在一起其实也可以不要的。 "from &index import app as application" & 这里的index 是个参数。看你的应用程序文件名叫啥了。如果 index.py 这里就是index关系大约是这样 &apache -----&wsgi---------&index.py另外遇到错误去apache的errorlog中查找。本文出自 “” 博客,请务必保留此出处
了这篇文章
类别:未分类┆阅读(0)┆评论(0)

我要回帖

更多关于 查找iphone关机 的文章

 

随机推荐