精华内容
参与话题
问答
  • Web基础(三)Python Web

    千次阅读 2018-11-14 19:11:49
    文章目录Python Web基础1. WSGI1.1 概述1.2 实现原理1、WSGI Server/gateway2、WSGI Application3、WSGI MiddleWare1.3 测试 WSGI服务器代码简析1.4 实现WSGI服务器1.5 生产环境中的Web服务器[Gunicorn]...

    Python Web基础

    在这里插入图片描述

    Web应用的本质:
    1. 浏览器发送一个HTTP请求
    2. 服务器收到请求,生成一个HTML文档
    3. 服务器把HTML文档作为HTTP响应的Body发送给浏览器
    4. 浏览器收到HTTP响应,从HTTP Body取出HTML文档并显示

    所以,最简单的Web应用就是先把HTML用文件保存好,用一个现成的HTTP服务器软件,接收用户请求,从文件中读取HTML,返回。我们上两篇博客已经详细讲解并实现了这样的HTTP服务器zjhttp,除此外Apache、Nginx、Lighttpd等这些常见的静态服务器就是干这件事情的。

    如果要动态生成HTML,就需要把上述步骤自己来实现。不过,接受HTTP请求、解析HTTP请求、发送HTTP响应都是苦力活,如果我们自己来写这些底层代码,还没开始写动态HTML呢,就得花个把月去读HTTP规范。正确的做法是底层代码由专门的服务器软件实现,我们用Python专注于生成HTML文档。

    1. WSGI

    Web服务器网关接口(Python Web Server Gateway Interface,缩写为WSGI)是为Python语言定义的Web服务器和Web应用程序或框架之间的一种简单而通用的接口。自从WSGI被开发出来以后,许多其它语言中也出现了类似接口。

    以前,如何选择合适的Web应用程序框架成为困扰Python初学者的一个问题,这是因为,一般而言,Web应用框架的选择将限制可用的Web服务器的选择,反之亦然。那时的Python应用程序通常是为CGI,FastCGI,mod_python中的一个而设计,甚至是为特定Web服务器的自定义的API接口而设计的。

    WSGI(有时发音作’wiz-gee’)是作为Web服务器与Web应用程序或应用框架之间的一种低级别的接口,以提升可移植Web应用开发的共同点。WSGI是基于现存的CGI标准而设计的。WSGI没有官方的实现, 因为WSGI更像一个协议。只要遵照这些协议,WSGI应用(Application)都可以在任何服务器(Server)上运行, 反之亦然。WSGI就是Python的CGI包装,相对于Fastcgi是PHP的CGI包装

    1.1 概述

    WSGI区分为两个部分
    1. 为“服务器”或“网关”。它用于接收、整理客户端发送的请求
    2. 为“应用程序”或“应用框架”。处理服务器程序传递过来的请求

    在这里插入图片描述

    如上图,Web服务器即第一部分,接收、整理客户端发送的请求,咱们前两篇博客使用C语言实现的zjhttp就是属于Web服务器部分;Web框架即为第二部分,即所谓的Web应用程序。开发Web应用程序的时候,通常会把常用的功能封装起来,成为各种框架,比如Flask,Django,Tornado(使用某框架进行web开发,相当于开发服务端的应用程序,处理后台逻辑)。但是,服务器程序和应用程序互相配合才能给用户提供服务,而不同应用程序(不同框架)会有不同的函数、功能。 此时,我们就需要一个标准,让服务器程序和应用程序都支持这个标准,那么,二者就能很好的配合了,这个标准就是 WSGI

    在处理一个WSGI请求时,服务器会为应用程序提供环境信息及一个回调函数(Callback Function)。当应用程序完成处理请求后,透过前述的回调函数,将结果回传给服务器。

    所谓的 WSGI 中间件同时实现了API的两方,因此可以在WSGI服务器和WSGI应用之间起调解作用。从Web服务器的角度来说,中间件扮演应用程序,而从应用程序的角度来说,中间件扮演服务器。“中间件”组件可以执行以下功能:
    1. 重写环境变量后,根据目标URL,将请求消息路由到不同的应用对象。
    2. 允许在一个进程中同时运行多个应用程序或应用框架。
    3. 负载均衡和远程处理,通过在网络上转发请求和响应消息。
    4. 进行内容后处理,例如应用XSLT样式表。

    1.2 实现原理

    WSGI 将 Web 组件分为三类

    • web服务器
    • web中间件
    • web应用程序

    wsgi基本处理模式为:
    WSGI Server -> WSGI Middleware -> WSGI Application

    1、WSGI Server/gateway

    wsgi server可以理解为一个符合wsgi规范的web server,接收request请求,封装一系列环境变量,按照wsgi规范调用注册的wsgi app,最后将response返回给客户端。以python自带的wsgiref为例,wsgiref是按照wsgi规范实现的一个简单wsgi server。它的代码不复杂。

    在这里插入图片描述

    1. 服务器创建socket,监听端口,等待客户端连接。
    2. 当有请求来时,服务器解析客户端信息放到环境变量environ中,并调用绑定的handler来处理请求。
    3. handler解析这个http请求,将请求信息例如method,path等放到environ中。
    4. wsgi handler再将一些服务器端信息也放到environ中,最后服务器信息,客户端信息,本次请求信息全部都保存到了环境变量environ中。
    5. wsgi handler 调用注册的wsgi app,并将environ和回调函数传给wsgi app
    6. wsgi app 将reponse header/status/body 回传给wsgi handler
    7. 最终handler还是通过socket将response信息塞回给客户端。

    2、WSGI Application

    wsgi application就是一个普通的callable对象,当有请求到来时,wsgi server会调用这个wsgi app。这个对象接收两个参数,通常为environ,start_response。environ就像前面介绍的,可以理解为环境变量,跟一次请求相关的所有信息都保存在了这个环境变量中,包括服务器信息,客户端信息,请求信息。start_response是一个callback函数,wsgi application通过调用start_response,将response headers/status 返回给wsgi server。此外这个wsgi app会return 一个iterator对象 ,这个iterator就是response body。这么空讲感觉很虚,对着下面这个简单的例子看就明白很多了。

    3、WSGI MiddleWare

    有些功能可能介于服务器程序和应用程序之间,例如,服务器拿到了客户端请求的URL, 不同的URL需要交由不同的函数处理,这个功能叫做 URL Routing,这个功能就可以放在二者中间实现,这个中间层就是 middleware。middleware对服务器程序和应用是透明的,也就是说,服务器程序以为它就是应用程序,而应用程序以为它就是服务器。这就告诉我们,middleware需要把自己伪装成一个服务器,接受应用程序,调用它,同时middleware还需要把自己伪装成一个应用程序,传给服务器程序。

    论是服务器程序、middleware 还是应用程序,都在服务端,为客户端提供服务,之所以把他们抽象成不同层,就是为了控制复杂度,使得每一次都不太复杂,各司其职。

    1.3 测试 WSGI服务器

    原理说得太多未免过于抽象,现在使用Python内置的纯Python代码编写的wsgiref服务器来体验一把WSGI服务器是如何工作的

    • 编写hello.py 作为一个Web应用程序

      def application(environ, start_response):
          start_response('200 OK', [('Content-Type', 'text/html')])
          return [b'<h1>Hello, World!</h1>']
      
    • 编写server.py作为一个WSGI服务器

      from wsgiref.simple_server import make_server
      # 导入编写的application函数
      from hello import application
      
      # 创建一个服务器,IP地址为空,端口是8000,传入函数application
      httpd = make_server('', 8000, application)
      print('Serving HTTP on port 8000...')
      # 开始监听HTTP请求:
      httpd.serve_forever()
      
    • 启动WSGI服务器

      python server.py
      
    • 使用客户端访问
      打开浏览器,输入http://localhost:8000/ ,在浏览器正常显示“Hello, World!”

    在这里插入图片描述

    代码简析

    上面的application()函数就是符合WSGI标准的一个HTTP处理函数,它接收两个参数:

    • environ:一个包含所有HTTP请求信息的dict对象
    • start_response:一个发送HTTP响应的函数

    而在application()函数中又调用了start_response函数

    该函数发送了HTTP响应的Header,注意Header只能发送一次,也就是只能调用一次start_response()函数。start_response()函数接收两个参数,一个是HTTP响应码,一个是一组list表示的HTTP Header,每个Header用一个包含两个strtuple表示。

    通常情况下,都应该把Content-Type头发送给浏览器。其他很多常用的HTTP Header也应该发送。然后,函数的返回值b'<h1>Hello, web!</h1>'将作为HTTP响应的Body发送给浏览器。

    有了WSGI,我们关心的就是如何从environ这个dict对象拿到HTTP请求信息,然后构造HTML,通过start_response()发送Header,最后返回Body。

    整个application()函数本身没有涉及到任何解析HTTP的部分,也就是说,底层代码不需要我们自己编写,我们只负责在更高层次上考虑如何响应请求就可以了。

    需要注意的是,application()函数必须由WSGI服务器来调用。有很多符合WSGI规范的服务器,我们可以挑选一个来用。但是我们仅将内置的wsgiref服务器用于测试,使我们编写的Web应用程序立马跑起来。

    1.4 实现WSGI服务器

    为了了解wsgi的工作原理,我们可以参照wsgiref源码,使用Python简单实现一个WSGI服务器

    import socket
    import StringIO
    import sys
    
    class WSGIServer(object):
    
        address_family = socket.AF_INET
        socket_type = socket.SOCK_STREAM
        request_queue_size = 1
    
        def __init__(self, server_address):
            # 创建socket,利用socket获取客户端的请求
            self.listen_socket = listen_socket = socket.socket(self.address_family, self.socket_type)
            # 设置socket的工作模式
            listen_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
            # 绑定socket地址
            listen_socket.bind(server_address)
            # socket active, 监听文件描述符
            listen_socket.listen(self.request_queue_size)
    
            # 获得serve的host name和port
            host, port = self.listen_socket.getsockname()[:2]
            self.server_name = socket.getfqdn(host)
            self.server_port = port
    
            self.headers_set = []
    
        def set_app(self, application):
            self.application = application 
    
        #启动WSGI server服务,不停的监听并获取socket数据。
        def serve_forever(self):
            listen_socket = self.listen_socket
            while True:
                self.client_connection, client_address = listen_socket.accept() #接受客户端请求
                #处理请求
                self.handle_one_request()
    
        def handle_one_request(self):
            self.request_data = request_data = self.client_connection.recv(1024)
            self.parse_request(request_data)
    
            # Construct environment dictionary using request data
            env = self.get_environ()
    
            #给flask\tornado传递两个参数,environ,start_response
            result = self.application(env, self.start_response)
            self.finish_response(result)
    
        #处理socket的http协议
        def parse_request(self, data):
            format_data = data.splitlines()
            if len(format_data):
                request_line = data.splitlines()[0]
                request_line = request_line.rstrip('\r\n')
                (self.request_method, self.path, self.request_version) = request_line.split() ## ['GET', '/', 'HTTP/1.1']
    
        # 获取environ数据并设置当前server的工作模式
        def get_environ(self):
            env = {}
            env['wsgi.version']      = (1, 0)
            env['wsgi.url_scheme']   = 'http'
            env['wsgi.input']        = StringIO.StringIO(self.request_data)
            env['wsgi.errors']       = sys.stderr
            env['wsgi.multithread']  = False
            env['wsgi.multiprocess'] = False
            env['wsgi.run_once']     = False
            # Required CGI variables
            env['REQUEST_METHOD']    = self.request_method    # GET
            env['PATH_INFO']         = self.path              # /hello
            env['SERVER_NAME']       = self.server_name       # localhost
            env['SERVER_PORT']       = str(self.server_port)  # 8888
            return env
    
        def start_response(self, status, response_headers, exc_info=None):
            server_headers = [('Date', 'Tue, 31 Mar 2015 12:54:48 GMT'), ('Server', 'WSGIServer 0.2')]
            self.headers_set = [status, response_headers + server_headers]
    
        #把application返回给WSGI的数据返回给客户端。
        def finish_response(self, result):
            try:
                status, response_headers = self.headers_set
                response = 'HTTP/1.1 {status}\r\n'.format(status=status)
                for header in response_headers:
                    response += '{0}: {1}\r\n'.format(*header)
                response += '\r\n'
                for data in result:
                    response += data
                self.client_connection.sendall(response)
                print(''.join(['> {line}\n'.format(line=line) for line in response.splitlines()]))
            finally:
                self.client_connection.close()
    
    SERVER_ADDRESS = (HOST, PORT) = '', 8888
    
    def make_server(server_address, application):
        server = WSGIServer(server_address)
        server.set_app(application)
        return server
    
    
    if __name__ == '__main__':
        if len(sys.argv) < 2:
            sys.exit('Provide a WSGI application object as module:callable')
        app_path = sys.argv[1]
        module, application = app_path.split(':') # 第一个参数是文件名,第二个参数时长文件内app的命名
        module = __import__(module)
        application = getattr(module, application) # getattr(object, name[, default]) -> value
        httpd = make_server(SERVER_ADDRESS, application)
        print('WSGIServer: Serving HTTP on port {port} ...\n'.format(port=PORT))
        httpd.serve_forever()
    
    

    1.5 生产环境中的Web服务器

    每个web框架都不是专注于实现服务器方面的,因此,在生产环境部署的时候,使用的服务器也不会简单的使用web框架自带的服务器,那么用于生产环境的服务器有哪些呢?

    Gunicorn

    Gunicorn(从Ruby下面的Unicorn得到的启发)应运而生:依赖Nginx的代理行为,同Nginx进行功能上的分离。由于不需要直接处理用户来的请求(都被Nginx先处理),Gunicorn不需要完成相关的功能,其内部逻辑非常简单:接受从Nginx来的动态请求,处理完之后返回给Nginx,由后者返回给用户。

    由于功能定位很明确,Gunicorn得以用纯Python开发:大大缩短了开发时间的同时,性能上也不会很掉链子。同时,它也可以配合Nginx的代理之外的别的Proxy模块工作,其配置也相应比较简单

    uWSGI

    使用C语言开发,和底层接触的更好,配置也比较方便,目前和gunicorn两个算是部署时的唯二之选。由于其可扩展的架构,它能够被无限制的扩展用来支持更多的平台和语言。目前,可以使用C,C++和Objective-C来编写插件

    uWSGI 既不使用wsgi协议也不用FastCGI协议,而是自创了一个uwsgi的协议,uwsgi协议是一个uWSGI服务器自有的协议,它用于定义传输信息的类型(type of information),每一个uwsgi packet前4byte为传输信息类型描述,它与WSGI相比是两样东西。据说该协议大约是fcgi协议的10倍那么快

    主要特点如下:

    • 超快的性能
    • 低内存占用(实测为apache2的mod_wsgi的一半左右)
    • 多app管理
    • 详尽的日志功能(可以用来分析app性能和瓶颈)
    • 高度可定制(内存大小限制,服务一定次数后重启等)

    uWSGI 服务器自己实现了基于uwsgi协议的server部分,因此我们只需要在uwsgi的配置文件中指定application的地址,uWSGI 就能直接和应用框架中的WSGI application通信

    bjoern

    是一个用C语言编写的,快速超轻量级的 Python WSGI服务器。
    它是最快速的,最小的并且是最轻量级的WSGI服务器。有以下特性:

    • 1000 行的C代码
    • 占用内存 600KB
    • 单线程没有其他协同程序
    • 可以绑定到TCP主机:端口地址和Unix套接字
    • 支持HTTP1.0/1.1,包含支持HTTP1.1的分块响应

    如果单纯追求性能,那uWSGI会更好一点,而Gunicorn则会更易安装和结合gevent。在阻塞响应较多的情况下,Gunicorn的gevent模式无疑性能会更加强大。功能实现方面,uWSGI会更多一些,配置也会更加复杂一些。

    2. Web应用开发

    常见的Python Web应用框架:

    • Django:全能型Web框架
    • Flask:一个使用Python编写的轻量级Web框架
    • web.py:一个小巧的Web框架
    • Bottle:和Flask类似的Web框架
    • Tornado:Facebook的开源异步Web框架

    2.1 服务器架构

    在这里插入图片描述

    2.1.1 Nginx

    Nginx(发音同engine x)是一个异步框架的 Web服务器,也可以用作反向代理,负载平衡器 和 HTTP缓存。该软件由 Igor Sysoev 创建,并于2004年首次公开发布。同名公司成立于2011年,以提供支持。

    Nginx是一款免费的开源软件,根据类BSD许可证的条款发布。一大部分Web服务器使用Nginx,通常作为负载均衡器。

    Nginx是一款面向性能设计的HTTP服务器,相较于Apache、lighttpd具有占有内存少,稳定性高等优势。与旧版本(<=2.2)的Apache不同,Nginx不采用每客户机一线程的设计模型,而是充分使用异步逻辑从而削减了上下文调度开销,所以并发服务能力更强。整体采用模块化设计,有丰富的模块库和第三方模块库,配置灵活。 在Linux操作系统下,Nginx使用epoll事件模型,得益于此,Nginx在Linux操作系统下效率相当高。同时Nginx在OpenBSD或FreeBSD操作系统上采用类似于epoll的高效事件模型kqueue。

    Nginx在官方测试的结果中,能够支持五万个并行连接,而在实际的运作中,可以支持二万至四万个并行连接

    反向代理

    在这里插入图片描述

    正向代理是指浏览器主动请求代理服务器,代理服务器转发请求到对应的目标服务器。而反向代理则部署在Web服务器上,代理所有外部网络对内部网络的访问。浏览器访问服务器,必须经过这个代理,是被动的。正向代理的主动方是客户端,反向代理的主动方是Web服务器

    在Python的Web开发中,较为成熟稳定的服务器架构一般是Nginx + uWSGI + Django。而实际上Nginx服务器并不是必须的,直接使用uWSGI + Djang完全是可以的,但这样一来,直接将uWSGI服务器暴露给了浏览器客户端,由此会导致诸多隐患。

    Nginx的优势
    1. 安全问题。客户端对Web服务器的访问需要先经过反向代理服务器,Nginx则只需开放某个接口,uWSGI本身是内网接口,这样可以防止外部程序对Web服务器的直接攻击。
    2. 负载均衡。反向代理服务器可以根据Web服务器的负载情况,动态地把HTTP请求交给不同的Web服务器来处理,前提是要有多个Web服务器。
    3. 提升Web服务器的IO性能。一个HTTP请求的数据,从客户端传输给服务器,是需要时间的,例如N秒,如果直接传给Web服务器,Web服务器就需要让一个进程阻塞N秒,来接收IO,这样会降低Web服务器的性能。如果使用Nginx作为反向代理服务器,先让反向代理服务器接收完整个HTTP请求,再把请求发给Web服务器,就能提升Web服务器的性能。将静态资源发送(js、css、图片等)、动态请求转发以及结果的回复交给Nginx处理,就不需要经过Web服务器。

    附录

    支持WSGI的Web应用框架有很多

    • BlueBream
    • bobo
    • Bottle
    • CherryPy
    • Django
    • Flask
    • Google App Engine’s webapp2
    • Gunicorn
    • prestans
    • Pylons
    • Pyramid
    • restlite
    • Tornado
    • Trac
    • TurboGears
    • Uliweb
    • web.py
    • web2py
    • weblayer
    • Werkzeug

    参考

    [参考资料1]
    [参考资料2]
    [参考资料3]
    [参考资料4]
    [参考资料5]

    展开全文
  • 本周课程主要讲解Python Web开发中的Web前端技术,其中包括HTML标记语言、CSS样式、JavaScript脚本语言、jQuery和Bootstrap布局等内容。由于本周知识点偏多故给出以下学习目标建议: 1. HTML:掌握基础语法和能够...
  • python web实例

    万次阅读 2018-08-10 15:11:48
    import web #定义访问路径 urls = ( '/(.*)', 'hello' ) #定义app app = web.application(urls, globals()) #定义访问类 class hello: def GET(self, name): print name re...
    #引入包
    import web  
      
    #定义访问路径
    urls = (  
        '/(.*)', 'hello'  
    )  
      
    #定义app
    app = web.application(urls, globals())  
      
    #定义访问类
    class hello:  
        def GET(self, name):  
            print name
            return 'Hello, ' + name + '!'  
      
    #启动
    if __name__ == "__main__":  
        app.run()  

     

    展开全文
  • Python Web开发之Flask原理与实战

    千人学习 2018-02-23 23:07:04
    Python Web开发之Flask视频开发教程,Flask是一个Python Web开发的微框架,快3天就能搭建一个功能齐全的网站。Flask不但是个人网站的佳选择,也在很多复杂的企业级网站中使用,应用越来越广泛。 本课程由清华学神...
  • [33]python Web 框架:Tornado

    万次阅读 多人点赞 2018-06-10 00:08:59
    Tornado:python编写的web服务器兼web应用框架 1.1.Tornado的优势 轻量级web框架 异步非阻塞IO处理方式 出色的抗负载能力 优异的处理性能,不依赖多进程/多线程,一定程度上解决C10K问题 WSGI全栈替代...

    1.Tornado

    • Tornado:python编写的web服务器兼web应用框架

    1.1.Tornado的优势

    • 轻量级web框架
    • 异步非阻塞IO处理方式
    • 出色的抗负载能力
    • 优异的处理性能,不依赖多进程/多线程,一定程度上解决C10K问题
    • WSGI全栈替代产品,推荐同时使用其web框架和HTTP服务器

    1.2.Tornado VS Django

    • Django:重量级web框架,功能大而全,注重高效开发
    • 内置管理后台
    • 内置封装完善的ORM操作
    • session功能
    • 后台管理
    • 缺陷:高耦合
    • Tornado:轻量级web框架,功能少而精,注重性能优越
    • HTTP服务器
    • 异步编程
    • WebSocket
    • 缺陷:入门门槛较高

    2.安装

    输入命令:

    pip install tornado
    

    备注:
    Tornado应该运行在类Unix平台,为了达到最佳的性能和扩展性,仅推荐Linux和BSD(充分利用Linux的epoll工具和BSD的kqueue达到高性能处理的目的)

    3.使用

    3.1.Tornado入门程序 - (一)

    #-*- coding:utf-8 -*-
    import tornado.web
    import tornado.ioloop
    
    
    #定义处理类型
    class IndexHandler(tornado.web.RequestHandler):
        #添加一个处理get请求方式的方法
        def get(self):
            #向响应中,添加数据
            self.write('好看的皮囊千篇一律,有趣的灵魂万里挑一。')
    
    if __name__ == '__main__':
        #创建一个应用对象
        app = tornado.web.Application([(r'/',IndexHandler)])
        #绑定一个监听端口
        app.listen(8888)
        #启动web程序,开始监听端口的连接
        tornado.ioloop.IOLoop.current().start()
    

    1 .在pycharm中直接运行代码
    2 .如果是在ubuntu,在命令窗口输入

    python 文件名.py
    

    使用浏览器访问

    4.Tornado 代码解析

    4.1.入门程序代码解析

    • tornado.web:tornado的基础web框架

      • RequestHandler:封装对请求处理的所有信息和处理方法
      • get/post/..:封装对应的请求方式
      • write():封装响应信息,写响应信息的一个方法
    • tornado.ioloop:核心io循环模块,封装linux的epoll和BSD的kqueue, tornado高性能处理的核心。

      • current()返回当前线程的IOLoop实例对象
      • start()启动IOLoop实力对象的IO循环,开启监听

    4.2.httpserver底层处理

    • httpserver监听端口
    tornado.httpserver.HTTPServer(app)
    httpserver.listen(port)
    
    • httpserver实现多进程操作
    tornado.httpserver.HTTPServer(app)
    httpserver.bind(port)
    httpserver.start(0/None/<0/num)
    
    # -*- coding:utf-8 -*-
    from tornado.web import Application,RequestHandler
    from tornado.ioloop import IOLoop
    from tornado.httpserver import HTTPServer
    
    class IndexHandler(RequestHandler):
        def get(self):
            self.write('给自己一点时间,理清所有的荒唐与期望。')
    
    if __name__ == '__main__':
        app = Application([(r'/',IndexHandler)])
        http_server = HTTPServer(app)
        #最原始的方式
        http_server.bind(8888)
        http_server.start(1)
    
        #启动Ioloop轮循监听
        IOLoop.current().start()
    

    同时打开两个窗口测试发现实现了多进程

    4.3.options配置

    • 全局配置
    tornado.options.define(
        name, default, type, multiple, help
    )
    
    • 命令行参数转换
    tornado.options.parse_command_line()
    
    #-*- coding:utf-8 -*-
    
    from tornado.web import RequestHandler,Application
    from tornado.ioloop import IOLoop
    from tornado.httpserver import HTTPServer
    import tornado.options
    
    #定义变量
    tornado.options.define('port',default=8000,type=int,help="this is the port >for application")
    
    class IndexHandler(RequestHandler):
       def get(self):
           self.write('我们既然改变不了规则,那就做到最好')
    
    if __name__ == '__main__':
       app = Application([(r'/',IndexHandler)])
       tornado.options.parse_command_line()
    
       http_server = HTTPServer(app)
       http_server.bind(tornado.options.options.port)
       http_server.start(1)
       #启动IOLoop轮循监听
       IOLoop.current().start()
    

    通过命令窗口输入port来访问
    通过使用我们命令窗口设定的port进行访问

    • 配置文件
    #即在当前py文件目录创建config文件,并在py代码中加入以下代码,
    tornado.options.parse_config_file("./config")
    
    • 配置模块:跟配置文件类似

    4.4.application配置

    • 程序调试之debug配置
    #自动重启+取消缓存模板+取消缓存静态文件+提供追踪信息
    tornado.web.Application([(..)], debug=True)
    
    注:开发之初可以设置debug=True方便调试,开发完毕改为False.
    
    • 路由信息初始化参数配置
    tonado.web.Application([(r””, Handler, {k:v})])
    def initialize(self, k)
    
    • 路由名称设置及反解析
    #名称设置
    tornado.web.Application([
        url(r””, handler, {k,v}, name=“”)
    ])
    
    #反解析操作
    reverse_url(name)
    

    实例

    # -*- coding:utf-8 -*-
    
    from tornado.web import Application, RequestHandler, url
    from tornado.ioloop import IOLoop
    from tornado.httpserver import HTTPServer
    
    
    class IndexHandler(RequestHandler):
    
        def get(self):
            self.write("<a href='"+self.reverse_url("login")+"'>用户登录</a>")
    
    
    class RegistHandler(RequestHandler):
        def initialize(self, title):
            self.title = title
    
        def get(self):
            self.write("注册业务处理:" + str(self.title))
    
    
    class LoginHandler(RequestHandler):
        def get(self):
            self.write("用户登录页面展示")
    
        def post(self):
            self.write("用户登录功能处理")
    
    
    if __name__ == "__main__":
        app = Application(
            [
                (r"/", IndexHandler),
                (r"/regist", RegistHandler, {"title": "会员注册"}),
                url(r"/login", LoginHandler, name="login"),
            ]
        )
    
        http_server = HTTPServer(app)
        http_server.listen(8000)
    
        IOLoop.current().start()
    

    4.5.参数传递

    • get方式传递参数
    get_query_arguments(name,default=_ARG_DEFAULT,strip=True)
    get_query_argument(name ,strip=True)
    
    • post方式传递参数
    get_body_arguments(name, default=_ARG_DEFAULT,strip=True)
    get_body_argument(name ,strip=True)
    

    实例

    # -*- coding:utf-8 -*-
    
    from tornado.web import Application, RequestHandler
    from tornado.ioloop import IOLoop
    from tornado.httpserver import HTTPServer
    
    
    class IndexHandler(RequestHandler):
    
        def get(self):
            # 获取get方式传递的参数
            username = self.get_query_argument("username")
            usernames = self.get_query_arguments("username")
    
            print (username)
            print (usernames)
    
        def post(self):
            # 获取post方式传递的参数
            username = self.get_body_argument("username")
            usernames = self.get_body_arguments("username")
    
            print (username)
            print (usernames)
    
    if __name__ == "__main__":
        app = Application([(r"/",IndexHandler)])
    
        app.listen(8000)
    
        IOLoop.current().start()
    
    #网页运行时需要传入参数
    #192.168.11.79:8000/?username=123
    
    • 混合方式
    get_arguments(..)/get_argument(..)
    

    实例

    # -*- coding:utf-8 -*-
    
    from tornado.web import Application, RequestHandler
    from tornado.ioloop import IOLoop
    
    
    class IndexHandler(RequestHandler):
    
        def get(self):
            # 获取get方式的参数
            user = self.get_argument("user")
            print("get方式获取参数:" + str(user))
    
        def post(self):
            # 获取post方式的参数
            user = self.get_argument("user")
            print("post方式获取参数:" + user.encode("utf-8"))
    
    
    if __name__ == "__main__":
        app = Application([(r"/", IndexHandler)])
    
        app.listen(8000)
    
        IOLoop.current().start()
    
    • 其他参数
    通过request获取参数数据
    method/host/uri/path/query/version/headers/body/remote_ip/files
    

    实例

    • request/json
    # -*- coding:utf-8 -*-
    
    from tornado.web import Application, RequestHandler
    from tornado.ioloop import IOLoop
    
    
    class IndexHandler(RequestHandler):
        def get(self):
            print self.request
    
            json_str = {"username": "admin", "password": "123123"}
            self.write(json.dumps(json_str))
    
    
    
    if __name__ == "__main__":
        app = Application([(r"/", IndexHandler)])
    
        app.listen(8000)
    
        IOLoop.current().start()
    
    • header
    • .add_header() .set_header() .set_default_headers()
      • 设置响应HTTP头, 前两者的不同点在于多次设置同一个项时, .add_header()叠加参数, 而.set_header()则以最后一次为准.
      • .set_default_headers()比较特殊, 是一个空方法, 可根据需要重写, 作用是在每次请求初始化RequestHandler时设置默认headers.
    • .clear_header() .clear()
      • .clear_header()清除指定的headers, 而.clear()清除.set_default_headers()以外所有的headers设置.
    # add_header
    self.add_header('Foo', 'one')
    self.add_header('Foo', 'two')
    # set_header
    self.set_header('Bar', 'one')
    self.set_header('Bar', 'two')
    
    # HTTP头的设置结果
    # Foo → one, two
    # Bar → two
    
    

    # -*- coding:utf-8 -*-
    
    from tornado.web import Application, RequestHandler
    from tornado.ioloop import IOLoop
    
    
    class IndexHandler(RequestHandler):
        def set_default_headers(self):
            # 第二种响应头设置方式
            print("---------> 响应头set_default_headers()执行")
            self.set_header("Content-type", "application/json; charset=utf-8")
            self.set_header("qiku", "奇酷信息")
    
        def get(self):
            # 第一种操作响应头的方式:
            # self.set_header("Content-type", "application/json")
            print("---------->get方法执行")
            self.write("{'name':'jerry'}")
            self.set_header("qiku", "qikuedu.com")
    
    
    if __name__ == "__main__":
        app = Application([(r"/", IndexHandler)])
    
        app.listen(8000)
    
        IOLoop.current().start()
    
    • writerror
      • .send_error()用于发送HTTP错误页(状态码). 该操作会调用.clear() .set_status()
      • .write_error()用于清除headers, 设置状态码, 发送错误页. 重写.write_error()可以自定义错误页.
    # -*- coding:utf-8 -*-
    
    from tornado.web import Application, RequestHandler
    from tornado.ioloop import IOLoop
    
    
    class IndexHandler(RequestHandler):
    
        def get(self):
            self.write("hello qikuedu.com")
    
            self.send_error(404, msg="页面丢失", info="家里服务器搞对象去了")
    
        def write_error(self, status_code, **kwargs):
            self.write("<h1>出错啦,工程师MM正在赶来的途中...</h1>")
            self.write("<p>错误信息:%s</p>" % kwargs["msg"])
            self.write("<p>错误描述:%s</p>" % kwargs["info"])
    
    
    if __name__ == "__main__":
        app = Application([(r"/", IndexHandler)])
    
        app.listen(8000)
    
        IOLoop.current().start()
    

    数据流

    • .write()

      • 将数据写入输出缓冲区. 如果直接传入dict, 那Tornado会自动将其识别为json, 并把Content-Type设置为application/json, 如果你不想要这个Content-Type, 那么在.write()之后, 调用.set_header()重新设置就好了. 需要注意的是, 如果直接传入的是list, 考虑到安全问题(json数组会被认为是一段可执行的JavaScript脚本, 且<script src="*/secret.json">可以绕过跨站限制),list将不会被转换成json.
    • .flush()

      • 将输出缓冲区的数据写入socket. 如果设置了callback, 会在完成数据写入后回调. 需要注意的是, 同一时间只能有一个"等待"的flush callback, 如果"上一次"的flush callback还没执行, 又来了新的flush, 那么"上一次"的flush callback会被忽略掉.
    • .finish()

      • 完成响应, 结束本次请求. 通常情况下, 请求会在return时自动调用.finish(), 只有在使用了异步装饰器@asynchronous或其他将._auto_finish设置为False的操作, 才需要手动调用.finish().
    • cookie

    # -*- coding:utf-8 -*-
    
    from tornado.web import Application, RequestHandler
    from tornado.ioloop import IOLoop
    
    
    class IndexHandler(RequestHandler):
    
        def get(self):
            self.write("hello qikuedu.com")
    
            self.set_cookie("loginuser", "admin老王")
    
            print self.get_cookie("loginuser")
    
            print self.cookies
    
    
    if __name__ == "__main__":
        app = Application([(r"/", IndexHandler)])
    
        app.listen(8000)
    
        IOLoop.current().start()
    

    页面

    • .render()

      • 返回渲染完成的html. 调用后不能再进行输出操作.
    • .redirect()

      • 重定向, 可以指定3xx重定向状态码. 调用后不能再进行输出操作.
    # 临时重定向 301
    self.redirect('/foo')
    # 永久重定向 302
    self.redirect('/foo', permanent=True)
    # 指定状态码, 会忽略参数 permanent
    self.redirect('/foo', status=304)
    
    • redirect
    # -*- coding:utf-8 -*-
    
    from tornado.web import Application, RequestHandler, url
    from tornado.ioloop import IOLoop
    from tornado.httpserver import HTTPServer
    
    
    class IndexHandler(RequestHandler):
    
        def get(self):
            self.write("<a href='"+self.reverse_url("login")+"'>用户登录</a>")
    
    
    class RegistHandler(RequestHandler):
        def initialize(self, title):
            self.title = title
    
        def get(self):
            self.write("注册业务处理:" + str(self.title))
    
    
    class LoginHandler(RequestHandler):
        def get(self):
            self.write("用户登录页面展示")
    
        def post(self):
            self.write("用户登录功能处理")
    
    
    if __name__ == "__main__":
        app = Application(
            [
                (r"/", IndexHandler),
                (r"/regist", RegistHandler, {"title": "会员注册"}),
                url(r"/login", LoginHandler, name="login"),
            ]
        )
    
        http_server = HTTPServer(app)
        http_server.listen(8000)
    
        IOLoop.current().start()
    
    展开全文
  • 我用了pythonweb.py做了一个 web service install web.py cd webpy 编辑python web service. #!/usr/bin/env python urls = ('/title_matching2','title_matching2') app = web.application(urls,globals()...
  • 之前写过 Windows 7下Python Web开发环境搭建笔记,今天写一下在Linux系统下搭建Python Web的开发测试环境。 我使用的系统是:ubuntu 14.04 server,CentOS 参考我的最新记录:CentOS release 6.10 下 Python 3.7.5...

    之前写过 Windows 7下Python Web开发环境搭建笔记,今天写一下在Linux系统下搭建Python Web的开发测试环境。

    我使用的系统是:ubuntu 14.04 server,CentOS 参考我的最新记录:CentOS release 6.10 下 Python 3.7.5 安装记录

    关于Python的版本

    进入Python的网站,鼠标移到导航条上的下载,我们会发现提供两下主版本的下载链接!

    这两个之间存在什么差别呢?

    个人理解,2.7.x的版本为更加稳定的版本,而3.x的版本则是比较前卫的版本,包含了很多新功能新特性之类的;

    但如果想要用Python开发一个新项目,那么该如何选择Python版本呢?大部分Python库都同时支持Python 2.7.x和3.x版本的,所以不论选择哪个版本都是可以的。

    但有一些需要注意的区别,参考:Python 2.7.x 和 3.x 版本的重要区别小结

     

    下载Python

     

    由于Bluemix中如果未指定版本,缺省情况下会选择 V2.7.10,所以我决定下载安装 V2.7.10。

    我的操作系统是ubuntu 14.04 server,Linux系统通常都是通过源码进行安装;

    可以直接使用以下命令下载:

     

    wget https://www.python.org/ftp/python/2.7.11/Python-2.7.11.tar.xz

     

    点击下图进入Python下载页面,找到下载地址;

    选择你想使用的版本:

    XZ格式的压缩率通常是最高的,所以我这里选择XZ格式的包;

     

     

    安装Python

     

    解压刚刚下载的安装包

     

    # xz -d Python-2.7.11.tar.xz
    # tar -xvf Python-2.7.11.tar

    进入文件目录:

     

     

    # cd Python-2.7.11

    配置

     

     

    # ./configure

    安装

     

     

    # make

    这里只需要执行 make 就可以了,  不需要执行 makeinstall。

     

    注意,系统中可能还没有安装 make,会出现如下提示:

     

    # make
    The program 'make' is currently not installed. You can install it by typing:
    apt-get install make

    然后我们可以根据提示,执行以下命令安装:

     

     

    # apt-get install make

    输出如下:

     

     

    # apt-get install make
    Reading package lists... Done
    Building dependency tree       
    Reading state information... Done
    Suggested packages:
      make-doc
    The following NEW packages will be installed:
      make
    0 upgraded, 1 newly installed, 0 to remove and 48 not upgraded.
    Need to get 119 kB of archives.
    After this operation, 328 kB of additional disk space will be used.
    Get:1 http://hk.archive.ubuntu.com/ubuntu/ trusty/main make amd64 3.81-8.2ubuntu3 [119 kB]
    Fetched 119 kB in 7s (16.0 kB/s)
    Selecting previously unselected package make.
    (Reading database ... 80371 files and directories currently installed.)
    Preparing to unpack .../make_3.81-8.2ubuntu3_amd64.deb ...
    Unpacking make (3.81-8.2ubuntu3) ...
    Processing triggers for man-db (2.6.7.1-1ubuntu1) ...
    Setting up make (3.81-8.2ubuntu3) ...

    安装成功之后再执行 make 命令,这个过程可能有点慢,需要等一会儿。

     

    以下为最后部分输出:

     

    Python build finished, but the necessary bits to build these modules were not found:
    _bsddb             _curses            _curses_panel   
    _sqlite3           _ssl               _tkinter        
    bsddb185           bz2                dbm             
    dl                 gdbm               imageop         
    readline           sunaudiodev        zlib            
    To find the necessary bits, look in setup.py in detect_modules() for the module's name.
    
    running build_scripts
    creating build/scripts-2.7
    copying and adjusting /home/aven/Python-2.7.11/Tools/scripts/pydoc -> build/scripts-2.7
    copying and adjusting /home/aven/Python-2.7.11/Tools/scripts/idle -> build/scripts-2.7
    copying and adjusting /home/aven/Python-2.7.11/Tools/scripts/2to3 -> build/scripts-2.7
    copying and adjusting /home/aven/Python-2.7.11/Lib/smtpd.py -> build/scripts-2.7
    changing mode of build/scripts-2.7/pydoc from 644 to 755
    changing mode of build/scripts-2.7/idle from 644 to 755
    changing mode of build/scripts-2.7/2to3 from 644 to 755
    changing mode of build/scripts-2.7/smtpd.py from 644 to 755
    /usr/bin/install -c -m 644 ./Tools/gdb/libpython.py python-gdb.py

     

    到这里就安装完成了,输入“Python”,然后回车看看吧!

    如何退出 Python 命令行? Ctrl + Z 就可以了。

     

    关于Pip

     

    pip是一个安装和管理Python包的工具,是easy_install的一个替换品。

    看到网上一些文章介绍Pip还需要单独安装,已经过时了,经过上面的步骤,Pip已经被安装好了;

     

    关于Python IDE

     

    什么是IDE?
    IDE= 集成开发环境= 把开发相关的各种环境(和工具)都集成到一起

    Python IDE= Python的集成开发环境= 把和Python开发相关的各种工具

    有几种可以选择:

     

     

     

    Hello World

    Python要求严格的缩进:

     

    [python] view plain copy
     
    1. #!/usr/bin/python  
    2. # -*- coding: UTF-8 -*-  
    3.   
    4. print 'hello world'  
    5.   
    6. for i in range(1,5):  
    7.     for j in range(1,5):  
    8.         for k in range(1,5):  
    9.             if( i != k ) and (i != j) and (j != k):  
    10.                 print 'hello world', i,j,k  

    保存文件,执行查看结果:

     

     

     

    小结

     

    到这里Python Web的开发环境就搭建完了,非常的简单!

    有的小伙伴可能怒了,我还没看到Web的影子呢!

    哈哈,我也是刚刚发现,Python和Go语言一样,Web服务器可以自己写;

     

    下一篇:《Python入门》第一个Python Web程序——简单的Web服务器

    展开全文
  • 师傅带徒弟学:Python Web之Django框架

    千人学习 2018-09-17 09:21:32
    扫码进群,领取资料+讲师答疑 ... Python WebPython语言一个重要的应用方面,Python Web有很多,其中Flask和Django框架是他们的佼佼者。Django是一个高级的Python Web框架,可以快速开发安全和可维护的网站。
  • 做网页开发少不了数据存储中心,在Java Web中常用的数据库是MySQL,但我们在这里不适用MySQL,而使用非关系型的数据库MongoDB.
  • Python Web 1 —— python和MongoDB安装

    千次阅读 2016-06-11 17:35:42
    做了很长时间的客户端,主要从事过Android软件开发和Unity 3D的游戏开发,之前还看过一段时间的Java Web,但是由于没有实际的应用,所以就搁置了很久。最近突然有对服务器后台编程产生了浓厚的兴趣,想试着用Python ...
  • Python Web项目(Python3.6.4+Django2.0)

    万次阅读 多人点赞 2018-02-01 18:19:17
    一、前言 Django是一个开放源代码的Web应用框架,由...由于我也是刚开始接触Python Web,不好给大家解释其中的区别,给大家推荐一片文章:浅谈MVC、MTV和MVVM,理解django框架中的MTV与MVC模式其中还有作者对MVVM的理
  • PYTHON WEB开发学习实录(中文高清版)

    千次下载 热门讨论 2013-03-22 21:07:20
    第1章欢迎来到Python世界 1.1 Python简介 视频教学:11分钟 1.2安装Python(Windows安装) 视频教学:8分钟 1.3使用带提示符的解释器 ...第15章PythonWeb开发之Django框架应用 附录各章习题参考答案
  • 本周课程主要讲解PythonWeb框架Django,具体有Django框架的安装、入门、URL路由配置、Model模型、View视图、Template模板、以及常用的web工具和其他核心功能。通过本周学习让学员可以掌握:Django框架的搭建、使用...
  • 浅谈Python Web

    千次阅读 2018-12-28 15:27:16
    最为入门的小菜: 可以认为就是把java web中的java换成了 python 抄自:https://blog.csdn.net/u012104219/article/details/80146252 今天这篇文章谈一谈Java Web开发和Python Web开发的区别。在这里我并不是鼓励大家...
  • python web开发入门

    万次阅读 2017-05-10 20:24:20
    ps:最近(18.2.26)对内容做了一些修改。 Python web开发通常都是从学习某一种框架开始,比如Django,flask。...Python web开发是web开发的子集,在学习如何用Python开发web应用之前,我们需要了解web服...
  • 师傅带徒弟学:Python Web之Flask框架

    千人学习 2018-09-06 10:36:16
    Python WebPython语言一个重要的应用方面,Python Web有很多,其中Flask和Django框架是他们的佼佼者。 Flask是一个Python实现的Web开发微框架。
  • python web框架 - Django

    千次阅读 2014-03-23 16:30:13
    Python下有许多款不同的 Web 框架。Django是重量级选手中最有代表性的一位。许多成功的网站和APP都基于Django。 Django是一个开放源代码的Web应用框架,由Python写成。Django遵守BSD版权,初次发布于2005年7月, 并...
  • 通过通"俗"易懂的讲课风格讲述python的实战开发基础,使用实战的思维导向式学习基础知识,让大家在知识点细节上掌握的更深刻。 本课程专注于web领域,适合web开发者学习和提高。 本课程在开头就会上手django框架...
  • 大家好,我叫亓官劼(qí guān jié ),这个《小白都能看懂的实战教程 手把手教你Python Web全栈开发》是一个零基础的实战教程,手把手带你开发一套系统,带你了解Python web全栈开发,目前正在连续更新中,如果...
  • pythonanywhere 部署 Python web项目

    千次阅读 2018-10-19 15:08:57
    一,上传代码包 打开首先 Files选项对话 .zip文件上传 现在文件已经上传,我们要进入Bash来解压缩它。 点击右上角Open Bash console here...接下来用以下代码来解压缩(建议先要对linux基本操作有个了解) ...$...
  • Python Web项目

    千次阅读 2019-07-01 17:10:31
    Python3.7.3+Django2.2.2 一 项目创建 1 在 D:\pythonTest 目录下按住 Shift + 鼠标右键 进入命令提示符 2 创建:django-admin startproject demo, 查看:dir或ls 二 启动 Django 服务 1 进入项目目录,并执行...
  • python Web开发

    千次阅读 2018-12-27 17:50:04
    本文参考自廖雪峰老师的python教程,旨在理清用pythonweb开发的思路。 一,HTTP 二,请求一个网页的流程 三,WSGI 四,Web框架 五,模板 六,总结 一,HTTP http get请求格式: GET /path HTTP/1.1 ...
  • python webapi

    千次阅读 2019-06-21 15:09:15
    目的:将python代码写的功能模块封装成webapi 我首先用vs2017搭建python flask web项目 在runserver.py文件中 init.py """ The flask application package. """ from flask import Flask app = Flask(__name__) ...
  • Python Web 框架

    2019-06-16 17:47:52
    Django是一个高级别的PythonWeb框架,它鼓励快速开发和干净、实用的设计。它是由经验丰富的开发人员构建的,它处理了Web开发中的许多麻烦,因此您可以专注于编写应用程序,而无需重新发明方向盘。它是免费的,开源的...
  • Python Web开发

    千次阅读 2016-06-24 09:36:19
    Web开发介绍 一、Web开发概述 1 C/S结构和B/S结构 C/S — Client/Server,即客户机/服务器结构 B/S — Browse/Server,即浏览器/服务器结构  2 B/S结构的优势 2.1 不用通知客户端安装某个软件 2.2 不用...
  • Python Web Demo

    千次阅读 2016-11-17 15:49:47
    Flask是一个使用 Python 编写的轻量级 Web 应用框架。其 WSGI 工具箱采用 Werkzeug ,模板引擎则使用 Jinja2 。Flask使用 BSD 授权。
  • Python web框架

    2017-04-09 21:59:07
    web2py非常用的重量级框架 CubicWeb Django-hotsauce Giotto Grok Pylons Reahl wheezy.web Zope2Glashammer Karrigell Kiss.py Lino Nagare Porcupine Pylatte Spyce Tipfy T
  • 本周课程主要通过Django框架开发Web商城项目,特别是网站的前台模块。具体内容有:商城前台界面搭建,会员注册登录与退出、商品展示,购物车实战、会员下单操作,后台订单处理,前台会员中心的订单处理等模块开发。...

空空如也

1 2 3 4 5 ... 20
收藏数 65,360
精华内容 26,144
关键字:

python web

python 订阅