汕头企业制作网站推广,合肥 中网站,抖音代运营大概多少钱一个月,一级a做爰片免费网站短视频3.1 Application settings 前面的学习中#xff0c;在创建tornado.web.Application的对象时#xff0c;传入了第一个参数——路由映射列表。实际上Application类的构造函数还接收很多关于tornado web应用的配置参数。 参数#xff1a; debug#xff0c;设置tornado是否工作… 3.1 Application settings 前面的学习中在创建tornado.web.Application的对象时传入了第一个参数——路由映射列表。实际上Application类的构造函数还接收很多关于tornado web应用的配置参数。 参数 debug设置tornado是否工作在调试模式默认为False即工作在生产模式。当设置debugTrue 后tornado会工作在调试/开发模式在此种模式下tornado为方便开发而提供了几种特性 自动重启tornado应用会监控的源代码文件当有改动保存后便会重启程序这可以减少手动重启程序的次数。需要注意的是一旦保存的更改有错误自动重启会导致程序报错而退出从而需要保存修正错误后手动启动程序。这一特性也可单独通过autoreloadTrue设置取消缓存编译的模板可以单独通过compiled_template_cacheFalse来设置取消缓存静态文件hash值可以单独通过static_hash_cacheFalse来设置提供追踪信息当RequestHandler或者其子类抛出一个异常而未被捕获后会生成一个包含追踪信息的页面可以单独通过serve_tracebackTrue来设置。使用debug参数的方法 import tornado.web
app tornado.web.Application([ ], debugTrue) 路由映射 先前在构建路由映射列表的时候使用的是二元元组如 [(r/, IndexHandler),] 对于这个映射列表中的路由实际上还可以传入多个信息如 [(r/, Indexhandler),(r/cpp, lewenHandler, {subject:c}),url(r/python, lewenHandler, {subject:python}, namepython_url)
] 对于路由中的字典会传入到对应的RequestHandler的initialize()方法中 from tornado.web import RequestHandler
class lewenHandler(RequestHandler):def initialize(self, subject):self.subject subjectdef get(self):self.write(self.subject) 对于路由中的name字段注意此时不能再使用元组而应使用tornado.web.url来构建。name是给该路由起一个名字可以通过调用RequestHandler.reverse_url(name)来获取该名子对应的url。 # -*- coding: utf-8 -*-
# __auther__ lewenimport tornado.web
import tornado.ioloop
import tornado.httpserver
import tornado.options
from tornado.options import options, define
from tornado.web import url, RequestHandlerdefine(port, default8000, typeint, helprun server on the given port )class IndexHandler(RequestHandler):def get(self, *args, **kwargs):python_url self.reverse_url(python_url)self.write(a href%sTornado /a % python_url)class MyHandler(RequestHandler):def initialize(self, subject):self.subject subjectdef get(self, *args, **kwargs):self.write(self.subject)if __name__ __main__:tornado.options.parse_command_line()app tornado.web.Application([(r/, IndexHandler),(r/cpp, MyHandler, {subject: c}),url(r/python, MyHandler, {subject: python}, namepython_url)],debugTrue)http_server tornado.httpserver.HTTPServer(app)http_server.listen(options.port)tornado.ioloop.IOLoop.current().start() 3.2 输入 下面几节主要讲解tornado.web.RequestHandler。 回想一下利用HTTP协议向服务器传参有几种途径 查询字符串query string)形如key1value1key2value2请求体body中发送的数据比如表单数据、json、xml提取uri的特定部分如/blogs/2016/09/0001可以在服务器端的路由中用正则表达式截取在http报文的头header中增加自定义字段如X-XSRFTokenlewen。现在来看下tornado中为提供了哪些方法来获取请求的信息。 1. 获取查询字符串参数 get_query_argument(name, default_ARG_DEFAULT, stripTrue) 从请求的查询字符串中返回指定参数name的值如果出现多个同名参数则返回最后一个的值。 default为设值未传name参数时返回的默认值如若default也未设置则会抛出tornado.web.MissingArgumentError异常。 strip表示是否过滤掉左右两边的空白字符默认为过滤。 get_query_arguments(name, stripTrue) 从请求的查询字符串中返回指定参数name的值注意返回的是list列表即使对应name参数只有一个值。若未找到name参数则返回空列表 [ ]。 strip同前不再赘述。 2. 获取请求体参数 get_body_argument(name, default_ARG_DEFAULT, stripTrue) 从请求体中返回指定参数name的值如果出现多个同名参数则返回最后一个的值。 default与strip同前不再赘述。 get_body_arguments(name, stripTrue) 从请求体中返回指定参数name的值注意返回的是list列表即使对应name参数只有一个值。若未找到name参数则返回空列表[]。 strip同前不再赘述。 说明 对于请求体中的数据要求为字符串且格式为表单编码格式与url中的请求字符串格式相同即key1value1key2value2HTTP报文头Header中的Content-Type为application/x-www-form-urlencoded 或 multipart/form-data。对于请求体数据为json或xml的无法通过这两个方法获取。 3. 前两类方法的整合 get_argument(name, default_ARG_DEFAULT, stripTrue) 从请求体和查询字符串中返回指定参数name的值如果出现多个同名参数则返回最后一个的值。 default与strip同前不再赘述。 get_arguments(name, stripTrue) 从请求体和查询字符串中返回指定参数name的值注意返回的是list列表即使对应name参数只有一个值。若未找到name参数则返回空列表[]。 strip同前不再赘述。 说明 对于请求体中数据的要求同前。 这两个方法最常用。 用代码来看上述六中方法的使用 # -*- coding: utf-8 -*-
# __auther__ lewenimport tornado.web
import tornado.ioloop
import tornado.httpserver
import tornado.options
from tornado.options import options, define
from tornado.web import RequestHandler, MissingArgumentErrordefine(port, default8000, typeint, helprun server on the given port.)class IndexHandler(RequestHandler):def post(self):query_arg self.get_query_argument(a)query_args self.get_query_arguments(a)body_arg self.get_body_argument(a)body_args self.get_body_arguments(a, stripFalse)# 参数获取范围是请全体和查询url中arg self.get_argument(a)args self.get_arguments(a)default_arg self.get_argument(b, tornado test)default_args self.get_arguments(b)try:missing_arg self.get_argument(c)except MissingArgumentError as e:missing_arg We catched the MissingArgumentError!print(e)missing_args self.get_arguments(c)rep query_arg:%sbr/ % query_argrep query_args:%sbr/ % query_argsrep body_arg:%sbr/ % body_argrep body_args:%sbr/ % body_argsrep arg:%sbr/ % argrep args:%sbr/ % argsrep default_arg:%sbr/ % default_argrep default_args:%sbr/ % default_argsrep missing_arg:%sbr/ % missing_argrep missing_args:%sbr/ % missing_argsself.write(rep)if __name__ __main__:tornado.options.parse_command_line()app tornado.web.Application([(r/, IndexHandler),],debugTrue)http_server tornado.httpserver.HTTPServer(app)http_server.listen(options.port)tornado.ioloop.IOLoop.current().start() 注意以上方法返回的都是unicode字符串 使用时注意思考 什么时候设置default什么时候不设置defaultdefault的默认值_ARG_DEFAULT是什么什么时候使用strip亦即什么时候要截断空白字符什么时候不需要4. 关于请求的其他信息 RequestHandler.request 对象存储了关于请求的相关信息具体属性有 method HTTP的请求方式如GET或POST;host 被请求的主机名uri 请求的完整资源标示包括路径和查询字符串path 请求的路径部分query 请求的查询字符串部分version 使用的HTTP版本headers 请求的协议头是类字典型的对象支持关键字索引的方式获取特定协议头信息例如request.headers[Content-Type]body 请求体数据remote_ip 客户端的IP地址files 用户上传的文件为字典类型型如 {form_filename1:[tornado.httputil.HTTPFile, tornado.httputil.HTTPFile], # 表单名称文件对象form_filename2:[tornado.httputil.HTTPFile,],...
} tornado.httputil.HTTPFile是接收到的文件对象它有三个属性 filename 文件的实际名字与form_filename1不同字典中的键名代表的是表单对应项的名字body 文件的数据实体content_type 文件的类型。 这三个对象属性可以像字典一样支持关键字索引如 request.files[form_filename1][0][body]。实现一个上传文件并保存在服务器本地的小程序upload.py # -*- coding: utf-8 -*-
# __auther__ lewenimport tornado.web
import tornado.ioloop
import tornado.httpserver
import tornado.options
from tornado.options import options, define
from tornado.web import RequestHandlerdefine(port, default8000, typeint, helprun server on the given port.)class IndexHandler(RequestHandler):def get(self):self.write(hello tornado.)class UploadHandler(RequestHandler):def post(self):files self.request.files # 用户上传的文件为字典类型img_files files.get(img) # 获取文件对象列表if img_files:img_file img_files[0][body] # 获取文件数据with open(./tornado.jpg, wb) as file:file.write(img_file)self.write(OK)if __name__ __main__:tornado.options.parse_command_line()app tornado.web.Application([(r/, IndexHandler),(r/upload, UploadHandler),], debugTrue)http_server tornado.httpserver.HTTPServer(app)http_server.listen(options.port)tornado.ioloop.IOLoop.current().start() 5. 正则提取uri tornado中对于路由映射也支持正则提取uri提取出来的参数会作为RequestHandler中对应请求方式的成员方法参数。若在正则表达式中定义了名字则参数按名传递若未定义名字则参数按顺序传递。提取出来的参数会作为对应请求方式的成员方法的参数。 # -*- coding: utf-8 -*-
# __auther__ lewenimport tornado.web
import tornado.ioloop
import tornado.httpserver
import tornado.options
from tornado.options import options, define
from tornado.web import RequestHandlerdefine(port, default8000, typeint, helprun server on the given port.)class IndexHandler(RequestHandler):def get(self):self.write(hello tornado.)class SubjectCityHandler(RequestHandler):def get(self, subject, city):self.write((Subject: %sbr/City: %s % (subject, city)))class SubjectDateHandler(RequestHandler):def get(self, date, subject):self.write((Date: %sbr/Subject: %s % (date, subject)))if __name__ __main__:tornado.options.parse_command_line()app tornado.web.Application([(r/, IndexHandler),(r/sub-city/(.)/([a-z]), SubjectCityHandler), # 无名方式(r/sub-date/(?Psubject.)/(?Pdate\d), SubjectDateHandler), # 命名方式])http_server tornado.httpserver.HTTPServer(app)http_server.listen(options.port)tornado.ioloop.IOLoop.current().start() 建议提取多个值时最好用命名方式。 3.3 输出 1. write(chunk) 将chunk数据写到输出缓冲区。如在之前的示例代码中写的 class IndexHandler(RequestHandler):def get(self):self.write(hello lewen!) 想一想可不可以在同一个处理方法中多次使用write方法 下面的代码会出现什么效果 class IndexHandler(RequestHandler):def get(self):self.write(hello lewen 1!)self.write(hello lewen 2!)self.write(hello lewen 3!)write方法是写到缓冲区的可以像写文件一样多次使用write方法不断追加响应内容最终所有写到缓冲区的内容一起作为本次请求的响应输出。 想一想如何利用write方法写json数据 import jsonclass IndexHandler(RequestHandler):def get(self):stu {name:zhangsan,age:24,gender:1,}stu_json json.dumps(stu)self.write(stu_json)实际上可以不用自己手动去做json序列化当write方法检测到传入的chunk参数是字典类型后会自动帮转换为json字符串。 class IndexHandler(RequestHandler):def get(self):stu {name:zhangsan,age:24,gender:1,}self.write(stu)两种方式有什么差异 对比一下两种方式的响应头header中Content-Type字段自己手动序列化时为Content-Type:text/html; charsetUTF-8而采用write方法时为Content-Type:application/json; charsetUTF-8。 write方法除了帮将字典转换为json字符串之外还帮将Content-Type设置为application/json; charsetUTF-8。 2. set_header(name, value) 利用set_header(name, value)方法可以手动设置一个名为name、值为value的响应头header字段。 用set_header方法来完成上面write所做的工作。 import jsonclass IndexHandler(RequestHandler):def get(self):stu {name:zhangsan,age:24,gender:1,}stu_json json.dumps(stu)self.write(stu_json)self.set_header(Content-Type, application/json; charsetUTF-8) 3. set_default_headers() 该方法会在进入HTTP处理方法前先被调用可以重写此方法来预先设置默认的headers。注意在HTTP处理方法中使用set_header()方法会覆盖掉在set_default_headers()方法中设置的同名header。 class IndexHandler(RequestHandler):def set_default_headers(self):print 执行了set_default_headers()# 设置get与post方式的默认响应体格式为jsonself.set_header(Content-Type, application/json; charsetUTF-8)# 设置一个名为lewen、值为python的headerself.set_header(lewen, python)def get(self):print 执行了get()stu {name:zhangsan,age:24,gender:1,}stu_json json.dumps(stu)self.write(stu_json)self.set_header(lewen, i love python) # 注意此处重写了header中的lewen字段def post(self):print 执行了post()stu {name:zhangsan,age:24,gender:1,}stu_json json.dumps(stu)self.write(stu_json)... ... 终端中打印出的执行顺序 get请求方式的响应header: post请求方式的响应header: 4. set_status(status_code, reasonNone) 为响应设置状态码。 参数说明 status_code int类型状态码若reason为None则状态码必须为下表中的。reason string类型描述状态码的词组若为None则会被自动填充为下表中的内容。CodeEnum NameDetails100CONTINUEHTTP/1.1 RFC 7231, Section 6.2.1101SWITCHING_PROTOCOLSHTTP/1.1 RFC 7231, Section 6.2.2102PROCESSINGWebDAV RFC 2518, Section 10.1200OKHTTP/1.1 RFC 7231, Section 6.3.1201CREATEDHTTP/1.1 RFC 7231, Section 6.3.2202ACCEPTEDHTTP/1.1 RFC 7231, Section 6.3.3203NON_AUTHORITATIVE_INFORMATIONHTTP/1.1 RFC 7231, Section 6.3.4204NO_CONTENTHTTP/1.1 RFC 7231, Section 6.3.5205RESET_CONTENTHTTP/1.1 RFC 7231, Section 6.3.6206PARTIAL_CONTENTHTTP/1.1 RFC 7233, Section 4.1207MULTI_STATUSWebDAV RFC 4918, Section 11.1208ALREADY_REPORTEDWebDAV Binding Extensions RFC 5842, Section 7.1 (Experimental)226IM_USEDDelta Encoding in HTTP RFC 3229, Section 10.4.1300MULTIPLE_CHOICESHTTP/1.1 RFC 7231, Section 6.4.1301MOVED_PERMANENTLYHTTP/1.1 RFC 7231, Section 6.4.2302FOUNDHTTP/1.1 RFC 7231, Section 6.4.3303SEE_OTHERHTTP/1.1 RFC 7231, Section 6.4.4304NOT_MODIFIEDHTTP/1.1 RFC 7232, Section 4.1305USE_PROXYHTTP/1.1 RFC 7231, Section 6.4.5307TEMPORARY_REDIRECTHTTP/1.1 RFC 7231, Section 6.4.7308PERMANENT_REDIRECTPermanent Redirect RFC 7238, Section 3 (Experimental)400BAD_REQUESTHTTP/1.1 RFC 7231, Section 6.5.1401UNAUTHORIZEDHTTP/1.1 Authentication RFC 7235, Section 3.1402PAYMENT_REQUIREDHTTP/1.1 RFC 7231, Section 6.5.2403FORBIDDENHTTP/1.1 RFC 7231, Section 6.5.3404NOT_FOUNDHTTP/1.1 RFC 7231, Section 6.5.4405METHOD_NOT_ALLOWEDHTTP/1.1 RFC 7231, Section 6.5.5406NOT_ACCEPTABLEHTTP/1.1 RFC 7231, Section 6.5.6407PROXY_AUTHENTICATION_REQUIREDHTTP/1.1 Authentication RFC 7235, Section 3.2408REQUEST_TIMEOUTHTTP/1.1 RFC 7231, Section 6.5.7409CONFLICTHTTP/1.1 RFC 7231, Section 6.5.8410GONEHTTP/1.1 RFC 7231, Section 6.5.9411LENGTH_REQUIREDHTTP/1.1 RFC 7231, Section 6.5.10412PRECONDITION_FAILEDHTTP/1.1 RFC 7232, Section 4.2413REQUEST_ENTITY_TOO_LARGEHTTP/1.1 RFC 7231, Section 6.5.11414REQUEST_URI_TOO_LONGHTTP/1.1 RFC 7231, Section 6.5.12415UNSUPPORTED_MEDIA_TYPEHTTP/1.1 RFC 7231, Section 6.5.13416REQUEST_RANGE_NOT_SATISFIABLEHTTP/1.1 Range Requests RFC 7233, Section 4.4417EXPECTATION_FAILEDHTTP/1.1 RFC 7231, Section 6.5.14422UNPROCESSABLE_ENTITYWebDAV RFC 4918, Section 11.2423LOCKEDWebDAV RFC 4918, Section 11.3424FAILED_DEPENDENCYWebDAV RFC 4918, Section 11.4426UPGRADE_REQUIREDHTTP/1.1 RFC 7231, Section 6.5.15428PRECONDITION_REQUIREDAdditional HTTP Status Codes RFC 6585429TOO_MANY_REQUESTSAdditional HTTP Status Codes RFC 6585431REQUEST_HEADER_FIELDS_TOO_LARGE AdditionalHTTP Status Codes RFC 6585500INTERNAL_SERVER_ERRORHTTP/1.1 RFC 7231, Section 6.6.1501NOT_IMPLEMENTEDHTTP/1.1 RFC 7231, Section 6.6.2502BAD_GATEWAYHTTP/1.1 RFC 7231, Section 6.6.3503SERVICE_UNAVAILABLEHTTP/1.1 RFC 7231, Section 6.6.4504GATEWAY_TIMEOUTHTTP/1.1 RFC 7231, Section 6.6.5505HTTP_VERSION_NOT_SUPPORTEDHTTP/1.1 RFC 7231, Section 6.6.6506VARIANT_ALSO_NEGOTIATESTransparent Content Negotiation in HTTP RFC 2295, Section 8.1 (Experimental)507INSUFFICIENT_STORAGEWebDAV RFC 4918, Section 11.5508LOOP_DETECTEDWebDAV Binding Extensions RFC 5842, Section 7.2 (Experimental)510NOT_EXTENDEDAn HTTP Extension Framework RFC 2774, Section 7 (Experimental)511NETWORK_AUTHENTICATION_REQUIREDAdditional HTTP Status Codes RFC 6585, Section 6- class Err404Handler(RequestHandler):对应/err/404def get(self):self.write(hello lewen)self.set_status(404) # 标准状态码不用设置reasonclass Err210Handler(RequestHandler):对应/err/210def get(self):self.write(hello lewen)self.set_status(210, lewen error) # 非标准状态码设置了reasonclass Err211Handler(RequestHandler):对应/err/211def get(self):self.write(hello lewen)self.set_status(211) # 非标准状态码未设置reasonUnknow 5. redirect(url) 告知浏览器跳转到url。 class IndexHandler(RequestHandler):对应/def get(self):self.write(主页)class LoginHandler(RequestHandler):对应/logindef get(self):self.write(form methodpostinput typesubmit value登陆/form)def post(self):self.redirect(/) 6. send_error(status_code500, **kwargs) 抛出HTTP错误状态码 status_code默认为500kwargs为可变命名参数。使用send_error抛出错误后tornado会调用write_error()方法进行处理并返回给浏览器处理后的错误页面。 class IndexHandler(RequestHandler):def get(self):self.write(主页)self.send_error(404, content出现404错误) 注意默认的write_error()方法不会处理send_error抛出的kwargs参数即上面的代码中content出现404错误是没有意义的。 尝试下面的代码会出现什么问题 class IndexHandler(RequestHandler):def get(self):self.write(主页)self.send_error(404, content出现404错误)self.write(结束) # 在send_error再次向输出缓冲区写内容 注意使用send_error()方法后就不要再向输出缓冲区写内容了 7. write_error(status_code, **kwargs) 用来处理send_error抛出的错误信息并返回给浏览器错误信息页面。可以重写此方法来定制自己的错误显示页面。 class IndexHandler(RequestHandler):def get(self):err_code self.get_argument(code, None) # 注意返回的是unicode字符串下同err_title self.get_argument(title, )err_content self.get_argument(content, )if err_code:self.send_error(err_code, titleerr_title, contenterr_content)else:self.write(主页)def write_error(self, status_code, **kwargs):self.write(uh1出错了程序员GG正在赶过来/h1)self.write(up错误名%s/p % kwargs[title])self.write(up错误详情%s/p % kwargs[content]) 3.4 接口与调用顺序 下面的接口方法是由tornado框架进行调用的可以选择性的重写这些方法。 1. initialize() 对应每个请求的处理类Handler在构造一个实例后首先执行initialize()方法。在讲输入时提到路由映射中的第三个字典型参数会作为该方法的命名参数传递如 class ProfileHandler(RequestHandler):def initialize(self, database):self.database databasedef get(self):...app Application([(r/user/(.*), ProfileHandler, dict(databasedatabase)),]) 此方法通常用来初始化参数对象属性很少使用。 2. prepare() 预处理即在执行对应请求方式的HTTP方法如get、post等前先执行注意不论以何种HTTP方式请求都会执行prepare()方法。 以预处理请求体中的json数据为例 import jsonclass IndexHandler(RequestHandler):def prepare(self):if self.request.headers.get(Content-Type).startswith(application/json):self.json_dict json.loads(self.request.body)else:self.json_dict Nonedef post(self):if self.json_dict:for key, value in self.json_dict.items():self.write(h3%s/h3p%s/p % (key, value))def put(self):if self.json_dict:for key, value in self.json_dict.items():self.write(h3%s/h3p%s/p % (key, value)) 用post方式发送json数据时 用put方式发送json数据时 3. HTTP方法 方法描述get请求指定的页面信息并返回实体主体。head类似于get请求只不过返回的响应中没有具体的内容用于获取报头post向指定资源提交数据进行处理请求例如提交表单或者上传文件。数据被包含在请求体中。POST请求可能会导致新的资源的建立和/或已有资源的修改。delete请求服务器删除指定的内容。patch请求修改局部数据。put从客户端向服务器传送的数据取代指定的文档的内容。options返回给定URL支持的所有HTTP方法。4. on_finish() 在请求处理结束后调用即在调用HTTP方法后调用。通常该方法用来进行资源清理释放或处理日志等。注意请尽量不要在此方法中进行响应输出。 5. set_default_headers() 6. write_error() 7. 调用顺序 通过一段程序来看上面这些接口的调用顺序。 # -*- coding: utf-8 -*-
# __auther__ lewen
import json
import tornado.web
import tornado.ioloop
import tornado.httpserver
import tornado.options
from tornado.options import options, define
from tornado.web import RequestHandlerdefine(port, default8000, typeint, helprun server on the given port.)class IndexHandler(RequestHandler):def set_default_headers(self):print(调用了set_default_headers())def initialize(self):print(调用了initialize())def prepare(self):print(调用了prepare())def write_error(self, status_code, **kwargs):print(调用了write_error())def get(self):print(调用了get())def post(self):print(调用了post())self.send_error(200) # 注意此出抛出了错误def on_finish(self):print(调用了on_finish())if __name__ __main__:tornado.options.parse_command_line()app tornado.web.Application([(r/, IndexHandler),], debugTrue)http_server tornado.httpserver.HTTPServer(app)http_server.listen(options.port)tornado.ioloop.IOLoop.current().start() 在正常情况未抛出错误时调用顺序为 set_defautl_headers()initialize()prepare()HTTP方法on_finish()在有错误抛出时调用顺序为 set_default_headers()initialize()prepare()HTTP方法set_default_headers()write_error()on_finish() 3.5 练习 1.将Application的设置参数目前只学习了debug抽离为一个字典类型变量settings并在构造Application对象时使用settings。
2.熟练使用RequestHandler的各种输入输出方法。
3.尝试抽象出BaseHandler基类继承自RequestHandler并在此基类中实现prepare解析json数据、write_error两个接口。 转载于:https://www.cnblogs.com/wenyule/articles/10353578.html