tornado是什么?
官方的介绍网上有太多,在此我不再述说,附上tornado官网地址简单的说一句:tornado用来做网站的后端的,就是一般人说的服务器。
除了tornado外,python还有flask,Django等一系列的web框架可以选用
为什么选择tornado
其实这里我选择tornado,对比flask、Django我认为tornado的学习成本很低,初学者可以很快上手,从而达到加强信心,进入打怪升级的状态。另外,对比其他的框架,tornado最方便的是在部署时,只需要在前端部署一个Nginx即可上生产环境。而flask,Django等都需要部署另外的WSGI server。对于初学者来说,多一个东西要部署,就多一套东西要学习,就容易出错而不知道为什么出错,最终导致没有信心继续钻研下去。对于tornado是属于异步非阻塞框架等等技术名词,我不在这个真`从零系列做任何讲解和框架间的对比
我建议学完这个教程后,可以去学习Django。大而全的Django帮你解决了极大部分的框架问题,例如ORM等,同时丰富的社区资源,基本上可以解决你在Django上遇到的所有问题。附带一个简单讲解WSGI、uwsgi、uWSGI
让我们开始吧~
安装tornado
建议在虚拟环境中安装tornado,这样你就可以使用不同的web框架同时不会导致包管理混乱。附上地址Anaconda 配置与安装
#利用pip进行安装
pip install tornado
#安装后,通过终端输入python后
import tornado
hello word
创建一个简单的hello word服务器
建议大家先按照我的文件目录架构创建自己的项目目录,为什么这样说呢?因为我习惯了我自己的架构,后续文章都会以我自己的项目架构为例子
文件架构
ArticleServer
|----conf
|--------config.conf
|----method
|--------__init__.py
|----handlers
|--------__init__.py
|--------MainHandlers.py
|----views
|----statics
|----server.py
|----application.py
|----urlRoute.py
server.py如下
#!/usr/bin/env python
# coding: utf-8
import tornado.ioloop
import tornado.web
import tornado.httpserver
from tornado.options import define, options
#application是我们创建的application.py
from application import application
#import sys 是为了输出和这个文件处于什么位置,若不需要输出,这个可以不import
import sys
#定义一个变量,options.port = 8887。这样的好处是,
#如果之后需要在tornado其他地方使用这个变量,
#就可以直接用options.port就可以获得了,例子下面代码有
define("port", default = 8887, help = "run on this port" ,type = int)
if __name__ == "__main__":
tornado.options.parse_command_line()
#根据application的设置,生成一个server
http_server = tornado.httpserver.HTTPServer(application)
# server调用监听方法,监听options.port(8887)端口
http_server.listen(options.port)
#为了打印现在server是来自哪个文件,以及在监听哪个端口
lib = sys.path[0] + '\t' + str(options.port)
print ('Tornado server is running at %s' %lib)
# 使用tornado封装好的epoll接口,简单说这句必须要有xD
tornado.ioloop.IOLoop.instance().start()
application.py如下
#!/usr/bin/env python
#-*-coding:utf-8-*-
import urlRoute
import sys
import tornado.web
import os
#urlRoute是我们创建的urlRoute.py文件
from urlRoute import url
#一些基础设定,下面讲的是,一个是html等页面模版的存放位置,
#一个是css等静态文件的存放位置
settings = {
'template_path':os.path.join(os.path.dirname(__file__),"views"),
'static_path':os.path.join(os.path.dirname(__file__),"static"),
}
# handlers指的是url中的内容
application = tornado.web.Application(
handlers = url,
**settings
)
urlRoute.py如下
#!/usr/bin/env python
#-*-coding:utf-8-*-
#找到对应的handler位置,并import
from handlers.MainHandler import MainHandler
# 存入到列表中,后续注册到server端,告诉server端不同地址,
# 应该找不同的handler,其中“/”代表的是根网站,例如:x.x.com.
# 若“/app”,则访问x.x.com/app可以访问对应的资源
url =[
(r"/",MainHandler),
]
为什么我会把urlRoute单独写一个文件?因为当你的网站页面多了之后,你会发现有大量的网页地址需要存,单独放一个文件,便于后期维护
Mainhandler.py如下
# -*- coding: utf-8 -*-
#!/usr/bin/env python
import tornado.web
# 注意url中import的MainHandler名字,必须跟这里handler的名字一样
class MainHandler(tornado.web.RequestHandler):
#用get的方式访问这个handler的话,就进入到get方法。
#这里没有写post的方法,如果用post的方法进入到这个handler会报错
def get(self):
#write方法是打印到浏览器。若想打开一个html文件之类的,就需要用render
self.write('hello word')
在server.py中,运行脚本
![](https://img.haomeiwen.com/i4763291/54b23184e5ea060e.png)
在浏览器中输入
localhost:8887
#或者
127.0.0.1:8887
![](https://img.haomeiwen.com/i4763291/6f68b0f441116551.png)
恭喜大家,已经写好了第一个网络服务器,是不是很简单?
如果大家不想写这么多文件,其实可以把server、handler、application、urlRoute都写到一个文件。
好了,经历过hello word的洗礼,我们来做一个小说网站吧~
小说获取
这篇文章没有爬下来的文件进行处理,如果通过txt文件的方式阅读是没有问题的,但通过服务端传输到浏览器中,会有问题。因为里面有javascipt以及css等向原网址请求的内容,会导致加载很慢,也有可能会打不开。所以补充了一篇,简单利用python处理文本
小说存放
因为我并没有写数据库的教程,这里也不用数据库存放的方式,使用打开对应的文件然后获取内容的方式。新建一个文件夹,取你自己喜欢的名字,但必须要以英文命名,再建不同的子文件来放不同的小说。我这里文章的名字没有使用全英,其实是不合适的。
![](https://img.haomeiwen.com/i4763291/7e25e903e9ac9fa0.png)
这种方式在正式的网站上,不建议用,因为文件io的读写速度很慢,会导致性能降低、并发上不去等问题,还是建议用数据库的方式
编写对应的handler(web应用)
我希望用户访问小说地址/a时,需要带上书名(name)以及章节数(num)的方式来请求。所以链接上应该是localhost:8887/a?name=zhuxian&num=1的模式
在handlers文件夹下新建一个文件,命名为ArticleHandler(其实文件名跟class名可以不一样,我习惯写成一样)
# -*- coding: utf-8 -*-
#!/usr/bin/env python
import tornado.web
import sys,os
class ArticleHandler(tornado.web.RequestHandler):
#用get的方式访问,用post的话会报错
def get(self):
if 'num' and 'name' in self.request.uri:
# 获取num和name参数,不存在则报缺少参数错误
articleName = self.get_argument('name')
articleNum = self.get_argument('num')
# 把参数组装成文件地址
filename = sys.path[0] + u'/article/%s/第%s章.txt' % (articleName,articleNum)
#检查文件是否存在,不存在则报文件不存在错误
if os.path.isfile(filename):
result = ''
# 打开对应文件,用只读的方式
with open(filename,'r') as f:
# 遍历获得的文件内容,并拼接成正确的字符串输出
for line in f.readlines():
# 去除'\n'的换行符,并且替换成html的换行标签
line = line.strip()
if line and line !=' ':
result = result + '<br><br>' +line
# 输出到网页
self.write(result)
else:
self.write('file does not exsit')
else:
self.write('missing parameter')
因为我的小说文本被我之前处理过了,所以这里需要二次处理才符合网页展示的方式,否则文字不会换行。大家按照自己的实际来修改代码
urlRoutes.py 需要增加
#!/usr/bin/env python
#-*-coding:utf-8-*-
from handlers.MainHandler import MainHandler
from handlers.ArticleHandler import ArticleHandler
url =[
(r"/",MainHandler),
(r"/a", ArticleHandler)
]
在server点击运行
![](https://img.haomeiwen.com/i4763291/6b5185216d088d76.png)
至于如何部署到线上服务器,或者做一个内网穿透到外网等,就不在这里讲述
网友评论