Python3中tornado高并发框架(3)-基本框架样式

13. tornado.httputil.HTTPFile对象

  1. tornado.httputil.HTTPFile对象作用:
    它是接收到的文件的对象
  2. 属性
    filename:文件的实际名字
    body: 文件的数据实体
    content_type:文件的类型
    在templates中新建upload.html
templates/upload.html中简单的上传页面
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>上传文件</title>
</head>
<body>
    <form action="/upload" method="post"   enctype="multipart/form-data">
        <input type="file" name="file"/>
        <input type="file" name="file"/>
        <input type="file" name="img"/>
        <input type="submit"    value="上传">
    </form>
</body>
</html>

 

index的添加:

#tornado.httputil.HTTPFile对象
class UpfileHandler(RequestHandler):        #上传文件
    def get(self, *args, **kwargs):
        self.render("upload.html")			#访问页面upfiles.html

    def post(self, *args, **kwargs):
        files = self.request.files		#从request这种拿到files
        print(files)
        self.write("上传成功")
       

 application添加:

# http:127.0.0.1:9000/upload
(r"/upload", index.UpfileHandler),

 

新建text文本,写上who are you ,上传后

#(浏览器输出)上传成功

Python3中tornado高并发框架(3)-基本框架样式
#(pychar输出){'file': [{'filename': '新建文本文档.txt', 'body': b'who are you!', 'content_type': 'text/plain'}]}  

#上传两个相同类型的文件
#(pychar输出){'file': [{'filename': '新建文本文档.txt', 'body': b'who are you!', 'content_type': 'text/plain'},{'filename': '新建文本文档2.txt', 'body': b'who are you!', 'content_type': 'text/plain'}]}

#"file"就是<input type="file" name="file"/> 中的name
#"filename"就是上传的文件的名字
#“body”就是文件的内容

#而相对于<input type="file" name="img"/>,上传为文件时
#"filename"就是上传的图片的名字
#"body"内容就会变成字节码b"......"
#“content_type”就是图片的类型
{"img":[{'filename': 'tupian.png', 'body': b'.......................', 'content_type': 'image/png'}]}


#如果上传多个不同类型的文件,request拿到files结构:
{
    'file': [
        {
            'filename': '新建文本文档.txt', 'body': b'who are you!', 'content_type': 'text/plain'
        },
        {
            'filename': '新建文本文档2.txt', 'body': b'who are you!', 'content_type': 'text/plain'
        }
    ],
    "img":[
        {
            'filename': 'tupian.png', 'body': b'.......................', 'content_type': 'image/png'
        }
    ]
}

完整版上传:

 

import os
import config
class UpfileHandler(RequestHandler):  # 上传文件

    """
    self.request.files结构:
    {'file': [{'filename': '新建文本文档.txt', 'body': b'who are you!', 'content_type': 'text/plain'},{'filename': '新建文本文档2.txt', 'body': b'who are you!', 'content_type': 'text/plain'}],"img":[{'filename': 'tupian.png', 'body': b'.......................', 'content_type': 'image/png'}]}
    """

    def get(self, *args, **kwargs):
        self.render("upload.html")

    def post(self, *args, **kwargs):
        filesDict = self.request.files
        for inputname in filesDict:
            fileArr = filesDict[inputname]  # 拿到对应key的value
            for filesObj in fileArr:  # 又拿到key
                # 存储路径
                filePath = os.path.join(config.BASE_DIRS, "upfile/" + filesObj.filename)
                # filesObj.filename新建file。字典取到上传文件的名字,并新建
                with open(filePath, "wb") as f:  # 打开新建的文件 ( w+用在纯文本上,wb+可以用在Exe文件)
                    f.write(filesObj.body)  # 一样的字典形式拿到value,写入 文本的body字段的内容,即value
        self.write("成功")

    def check_xsrf_cookie(self):
        # 非常有用的在单页面禁用xsrf_cookie的检查
        return True

http://127.0.0.1:9000/upload

Python3中tornado高并发框架(3)-基本框架样式

Python3中tornado高并发框架(3)-基本框架样式

 

14.响应输出

  1. write
    原型:self.write(chunk) # chunk是响应浏览器的数据
    作用:
    1. 将chunk数据写到输出缓冲区。
    -----------缓冲区刷新:1.程序结束;2.手动刷新;3缓冲区满;4.遇到\n
    2.利用write方法写json数据

    ##刷新缓冲区
        self.finish
                刷新缓冲区,并关闭当前请求通道,即后面的数据不在传输
               
    ##缓冲区的内容输出到浏览器不用等待请求处理完成
        self. flush()
            self.write()会先把内容放在缓冲区,正常情况下,当请求处理完成的时候会自动把缓冲区的内容输出到浏览器,但是可以调用 self.flush()方法,这样可以直接把缓冲区的内容输出到浏览器,不用等待请求处理完成.

index.py添加:

class WriteHandler(tornado.web.RequestHandler):
    def get(self, *args, **kwargs):
        self.write("good boy1")
        self.write("good boy2")
        self.write("good boy3")
        self.finish()  # 刷新缓存区,并关闭请求通道,导致后面的good boy4无法传输
        self.write("good boy4")

#配置application中的url


(r"/write", index.WriteHandler),     #响应输出
(r"/json1", index.Json1Handler),  # 测试json1
(r"/json2", index.Json2Handler),  # 测试json2

Json2Handler,Json1Handler之前有实现。。。。。

    ##序列化
        json,jsonStr = json.dumps()
            需要导入json库,对应的Handler中编写字典, jsonStr = json.dumps(per) 将字典转化为json的字符串
             #(浏览器输出){"name": "nick", "age": 18, "height:": 170, "weight": 70}
但是你会发现,其实我们不需要这样写,直接用write也能转化。json还要进行下文的设置响应头
但是前者json转化的在谷歌浏览器F12中Network中json1文本中的Respose Headers里面,
Content Type 为 text/heml,而后者write转换后为appliction/json。
             text/heml浏览器会将这个当成页面进行渲染,所以应为json类型
            ###在线解析json数据结构 ,https://c.runoob.com/front-end/53 

 http://127.0.0.1:9000/json2

Python3中tornado高并发框架(3)-基本框架样式

 

#预先设置报文头
class Headerhandler(RequestHandler):
    def set_default_headers(self):
        self.set_header("Content-Type", "applictions/json;charset=UTF-8") #预先设置报文头
    def post(self, *args, **kwargs):  #下面的就不必再次书写了
        pass
    def get(self, *args, **kwargs):
        pass

 ##设置响应头
        self.set_header(name,value)
            self.set_header("Content-Type","applictions/json;charset=UTF-8")
            self.set_header("good","boy")   #自定义设置
            作用:手动设置一个名为name值为value的响应头字段(Respose Headers)
            参数:name:字段名称
                value:字段值
            
     ###text/html和text/plain的区别
            1、text/html的意思是将文件的content-type设置为text/html的形式,浏览器在获取到这种文件时会自动调用html的解析器对文件进行相应的处理。
            2、text/plain的意思是将文件设置为纯文本的形式,浏览器在获取到这种文件时并不会对其进行处理
    
    ##默认的headers
        set_default_headers()
            作用:
                def set_default_headers(self):
                在进入http响应方法之前被调用,可以重写该方法来预先设置默认的headers
                这样类下面的各种方法都不用再去设置header了,默认为set_default_headers里面的
                以后规范都在set_default_headers里面进行设置header
            注意:
                在http处理方法中(这里暂为get方法)使用set_header设置的子弹会覆盖set_default_headers里的默认设置字段

#预先设置报文头
class Headerhandler(RequestHandler):
    def set_default_headers(self):
        self.set_header("Content-Type", "applictions/json;charset=UTF-8") #预先设置报文头
    def post(self, *args, **kwargs):  #下面的就不必再次书写了
        pass
    def get(self, *args, **kwargs):
        pass

   ##设置状态码
        self.set_status(status_code,reason=None)
            作用:为响应设置状态码
             self.set_status(404,"bad boy")
            参数:status_code (状态码的值,int类型)
                        如果reason=None,则状态码必须为正常值,列如999
                reason (描述状态码的词组,string字符串类型)

#设置状态码
class StatusHandler(RequestHandler):
    def get(self, *args, **kwargs):
        self.set_status(404,reason="Dont find!")
        self.write("*****")  #返回Status Code:404 Dont find!

 

##重定向
        self.redirect()
            重定向跳转到其他页面,比如self.redirect("/write")跳转到http://127.0.0.1:9000/wtite

#重定向
class RedirectHandler(RequestHandler):
    def get(self,*args,**kwargs):
        self.redirect("/write")    #self.redirect重定向

##抛出HTTP错误状态码,默认为500,   tornado会调用write_error()方法并处理
        self.send_error(status_code=500,**kwargs)  #  抛出错误

  ##接收错误,并处理。所以说上面这两个必须连用。
        self.write_error(status_code,**kwargs)  #    接收返回来的错误并处理错误

#自定义错误页面
访问http://127.0.0.1:9000/error?flag=0 进行测试

class ErrorHandler(RequestHandler):
    def write_error(self, status_code, **kwargs):
        if status_code==500:
            code = 500
            #返回500界面
            self.write("服务器内部错误")
        elif  status_code==400:
            code = 400
            #返回404界面
            self.write("预先设置错误")
        self.set_status(code)
    def get(self, *args, **kwargs):
        flag = self.get_query_argument("flag")# 获取单个键值
        
        #self.get_query_argument('a')  # 如果同时传递多个a的参数,那么会采用后面覆盖前面的原则
        
        if flag == "0":
            self.send_error(500)
            #注意在self.send_error(500)以下同级的内容不会继续执行,
        self.write("right")

注册这个类,

# http://127.0.0.1:9000/error?flag=0
(r"/error", index.ErrorHandler),

http://127.0.0.1:9000/error?flag=4

Python3中tornado高并发框架(3)-基本框架样式

15.接口调用顺序

方法
1.def initialize(),
作用:初始化

2.def preare()方法
作用:预处理方法,在执行对应的请求方法之前调用
注意:任何一种http请求都会执行prepare方法
所以可以在这里进行反爬虫,验证用户是否符合条件。
3.HTTP方法
get:在传参的时候会将参数拼接到UTL的后面;速度快,效率高,不安全,传输数据量小
post:在传参时则是单独打包并发送;传输慢,效率低,传输数据量大,安全;(一般修改服务器的数据时就用post,其他时候就用get)
head :类似get请求,只是相应中没有具体的内容,用户获取报文头
delete:请求服务器到删除指定的资源
put :从客户端向服务器传送指定内容
patch:请求修改局部内容
options:返回URL支持的所有HTTP方法

4.def set_default_headers()
作用:设置响应头
5.def write_error()
作用:出现异常就提醒(如邮件提醒)机制并跳转到错误页面
6.def on_finish()
作用:在请求处理结束后执行,在该方法中进行一个资源的清理释放(各种方法调用中开启的空间释放–内存),或者是日志处理(当请求完成后的访问信息记录)
注意:尽量不要在该方法中进行响应输出
比如进行get请求完成后调用on_finish(),进行资源的清理释放

class IndexHandler(RequestHandler):
	def get(self, *args, **kwargs):
		pass
	def post(self, *args, **kwargs):
		pass
    def on_finish(self):
        pass

顺序

  1. 在正常情况未抛出错误时的顺序:

set_default
initialize
prepare
get/post
on_finish

测试如下:

views/index中的代码:

class TextHandler(RequestHandler):
    def initialize(self):
        print("initialize")
    def prepare(self):
        print("prepare")
    def get(self,*args,**kwargs):	#或者post
        print("get")
    def set_default_headers(self):
        print("set_default_hearders")
    def write_error(self,status_code,**kwargs):
        print("write_error")
    def on_finish(self):
        print("on_finish")

#application中配置路由
(r"/test",index.TextHandler) , #测试接口调用顺序

#浏览访问后
#(pycharm输出):
set_default_hearders
initialize
prepare
get
on_finish

  1. 在抛出错误的情况下的顺序

set_default_headers
initialize
prepare
get
set_default_headers
write_error
on_finish

测试如下:

views/index中
class TextHandler(RequestHandler):
    def initialize(self):
        print("initialize")
    def prepare(self):
        print("prepare")
    def get(self,*args,**kwargs):
        print("get")
        self.send_error(500)
        self.write("抛出错误500")
    def set_default_headers(self):
        print("set_default_headers")
    def write_error(self,status_code,**kwargs):
        print("write_error")
        self.write("500服务器错误")
    def on_finish(self):
        print("on_finish")
浏览器访问后
#(pycharm输出):

set_default_headers
initialize
prepare
get
set_default_headers
write_error
on_finish
ERROR:tornado.access:500 GET /text (127.0.0.1) 0.83ms
ERROR:tornado.application:Uncaught exception GET /text (127.0.0.1)
HTTPServerRequest(protocol='http', host='127.0.0.1:9000', method='GET', uri='/text', version='HTTP/1.1', remote_ip='127.0.0.1', headers={'Host': '127.0.0.1:9000', 'User-Agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:83.0) Gecko/20100101 Firefox/83.0', 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8', 'Accept-Language': 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2', 'Accept-Encoding': 'gzip, deflate', 'Connection': 'keep-alive', 'Cookie': 'csrftoken=kYvwi4JlbaFXkvvxF4qpEaScrcMF68e4', 'Upgrade-Insecure-Requests': '1'})
Traceback (most recent call last):
  File "/home/hlx2/anaconda3/lib/python3.6/site-packages/tornado/web.py", line 1509, in _execute
    result = method(*self.path_args, **self.path_kwargs)
  File "/home/hlx2/Linux-64/tornado_tutorial/views/index.py", line 18, in get
    self.write("抛出错误500")
  File "/home/hlx2/anaconda3/lib/python3.6/site-packages/tornado/web.py", line 708, in write
    raise RuntimeError("Cannot write() after finish()")
RuntimeError: Cannot write() after finish()

 

 

 

 

https://blog.csdn.net/weixin_43097301/article/details/84981441

上一篇:11高阶函数作业


下一篇:python函数的万能参数