After reading this article, you will be able to do it on your own:

  • You can write a simple static web page on the server and access it
  • You can write interfaces to your App to provide Json data
  • The server periodically performs a task


The last article by accessing the public number to obtain the daily latest information of the article a “this time, he through the public number to access the latest 1024 information information”, really did not expect, everyone’s enthusiasm once so high, resulting in my server pressure is very big. I was really surprised, but thank you all for your support. I promised you last time that I would tell you what I needed to do to achieve that function. So, this time I’m going to focus on how to use Tornado to build your own server. We’ll see you next time.

I bet 85% of you won’t get through this article. That’s how people feel about themselves.

Teaching a man to fish is better than teaching him to fish, which is why I am writing these articles. Asked since to the public, visit the grass today, then tomorrow I can, through public access to news of the latest news every day, or I focus on the weibo updates, or TV drama again with new, or if there was a new video video web site, or whether some BBS sent the latest posts, even together every morning, Can through their own algorithm combined with yesterday’s stock data, to predict today’s market rise and fall, the principle behind these things are actually similar. So, do not limit your thinking to a point, to spread, to let go, so that there will be the emergence of SAO operation.

Ok, enough nonsense, let’s talk about our hero today: Tornado.

What is a Tornado

Tornado is Tornado. Oh no, Tornado is an open source version of Web server software. Tornado is very different from the mainstream Web server frameworks today (including most Python frameworks) : it is non-blocking and quite fast.

Tornado needs to be written in Python, so in this series, we all use Python to do things, just like I said before, Python is the most suitable language for doing things!

Here I would like to say that there are many kinds of Web frameworks, different languages have different frameworks, and their characteristics are different. As for Ptyhon, there are several Web frameworks developed with Python, such as Django, Flask and Tornado, which also have their own characteristics. So, WHAT I’m saying is, in terms of which framework to use, please make your choice based on your own needs. Don’t blindly grab a casual use, this will pit yourself in the future. We here, is a small service, use for their own entertainment, so, there is no so much concern, just grab one with OK, this is not, I catch Tornado.

Get Tornado on the server

First, the server or your local machine should have Python (Python3 is recommended). Second, your machine should have PIP.

We need to install Tornado through PIP

1# pip install tornado
Copy the code

If you want to test whether the installation is successful or not, you only need to enter Python and enter Import Tornado. If no error is reported, the installation is successful.

Next, let’s do some local configuration.

Locally, I recommend PyCharm for the IDE. This IDE function is ok, if you already have your own IDE, you can skip here.

PyCharm has two downloadable versions on its website:



I recommend downloading the first version, Professional, which is very powerful and supports plug-ins for many Web frameworks.

But many people will find that this is a paid version of ah, so how to use?

When PyCharm is turned on for the first time, select License Server activation and fill in: http://im.js.cn:8888 or http://idea.java.sx/ or http://xidea.online, then click Activate to Activate.

Next, we need to synchronize the local code with the server-side code, map it, and set it up very easily. Here, we assume that the remote server address is 39.11.12.123.

In Tools -> Deployment -> Configuration:



Click the + sign in the upper left corner:



In the dialog box that appears, write the name casually, but select SFTP below.



In the first red box, fill in the IP address of the remote server: 39.11.12.123. In the second box, fill in the name of your login account on the server, which is usually root.



Then on the second page, in the Mapping, in the second red box, fill in the project directory address of your machine, and in the third red box fill in the project directory address on the server (pre-built).



Then click OK. Next, click the check box on Tools -> Deployment -> Automatic Upload so that each time you write a file, the code is automatically synchronized to the server.



Each time you need to synchronize, go to Tools -> Deployment and choose ‘Upload to XXXX’, or right-click on the file icon and choose ‘Deployment’. It’s very convenient. A successful upload would look something like this:



Ok, so we’re going to try to write our code. However, Tornad’s “Hello World” is a good first look for those of you who are new to the new framework.

 1import tornado.ioloop
 2import tornado.web
 3
 4class MainHandler(tornado.web.RequestHandler):
 5    def get(self):     # 3
 6        self.write("Hello, world")     # 4
 7
 8def make_app():
 9    return tornado.web.Application([
10        (r"/", MainHandler),     # 211]) 12 13if __name__ == "__main__":
14    app = make_app()     # 1
15    app.listen(8888)
16    tornado.ioloop.IOLoop.current().start()
Copy the code

In this, the most critical, there are several places:

  1. Make_app () declares a Tornado Application that specifies the URL path for the server to receive processing.
  2. The server receives the URL and passes the request to MainHandler() for processing.
  3. The get method in MainHandler is used to handle HTTP GET requests.
  4. Returns a single string.

OK, the simple analysis above is the logic of Tornado handling an online request. With this logic out of the way, let’s start by simply writing our own server-side code.

Lu yards moment

To clarify our two objectives:

  • Our website has access to the database and is displayed on the web page
  • Our website can provide data interface function for App and return data in Json format.

Okay, so we’re going to get up and masturbate code, sorry, masturbate code.

Follow what we said above, define the URL path, and then write the Handler. Therefore, I will first in accordance with this idea, the project catalog in this way to establish the following:



Next, we write the following code in the main.py file:

 1class Application(tornado.web.Application):
 2    def __init__(self):
 3        handlers = [
 4            (r"/web/", WebHandle),
 5            (r"/json/", JsonHandle),
 6        ]
 7        # Define tornado server configuration items, such as static/templates directory location, debug level, etc
 8        settings = dict(
 9            debug=True,
10            static_path=os.path.join(os.path.dirname(__file__), "static"),
11            template_path=os.path.join(os.path.dirname(__file__), "templates")
12        )
13        tornado.web.Application.__init__(self, handlers, **settings)
14
15
16if __name__ == "__main__":
17    print("Tornado server is ready for service\r")
18    Application().listen(8000, xheaders=True)
19    tornado.ioloop.IOLoop.current().start()
Copy the code

Here’s a quick explanation: We define two handlers, one to return the web version and one to return the Json version. Our Application is also written differently from the Hellow World example, where we can customize a lot of Settings, such as path, Debug mode and so on. So let’s see what happens with this Handler:

1# views.json
2class JsonHandle(tornado.web.RequestHandler):
3    def get(self, *args, **kwargs):
4        self.write("json view"5 6)# views.web
7class WebHandle(tornado.web.RequestHandler):
8    def get(self, *args, **kwargs):
9        self.write("web view")
Copy the code

Here are two extremely simple implementations to look at:





The following is a page with incorrect url access, because we have Debug mode enabled, so the page looks like this:



The 404 page is a problem that we’ll talk about later.

So here we have one place that I don’t know if you noticed, but it’s pretty inflexible, which is where the URL matches up here. This specifies that http://xxxxxx/json/ can only be handled by JsonHandler, but if http://xxxxxx/json/XX comes, it will report an error and the page was not found. To make our service more powerful and robust for handling such requests, we decided to add a new URl_router that, to some extent, controls our URL matching.

 1""" 2 url_router.py 3"""
 4def include(module):
 5    res = import_module(module)
 6    urls = getattr(res, 'urls', res)
 7    return urls
 8
 9
10def url_wrapper(urls):
11    wrapper_list = []
12    for url in urls:
13        path, handles = url
14        if isinstance(handles, (tuple, list)):
15            for handle in handles:
16                pattern, handle_class = handle
17                wrap = ('{0} {1}'.format(path, pattern), handle_class)
18                wrapper_list.append(wrap)
19        else:
20            wrapper_list.append((path, handles))
21    return wrapper_list
Copy the code

Json_urls.py and web_urls.py should be created in views.json and views.web respectively:

 1""" 2 main.py 3"""
 4class Application(tornado.web.Application):
 5    def __init__(self):
 6        # >>>> Different place to start
 7        handlers = url_wrapper([
 8            (r"/json/", include('views.json.json_urls')),
 9            (r"/web/", include('views.web.web_urls'11)), 10])# Different places to end <<<<
12        # Define tornado server configuration items, such as static/templates directory location, debug level, etc13 to 14""" 15 json_urls.py 16"""        
17urls=[
18    (r' ', JsonHandle)
19]
20
21""" 22 web_urls.py 23"""
24urls = [
25    (r"", WebHandle)
26]
Copy the code

This way, it looks a little messy, but it’s pretty flexible. To enrich our URL. For example, if I wanted to add a URL to view all json files, I would simply add a (r’/all’, GetAllHandler) to json_urls and implement GetAllHandler in json_view.py. When this is done, our server can handle both http://xxxxxx/json/ and http://xxxxxx/json/all urls at the same time, with different handlers.

At this point, our general framework is basically complete. Handler handler handler handler handler handler handler handler Handler Handler Handler

Because what we want to achieve is to read the data from the database and display it on the web page, so, here we use the PyMongo library. This library is designed specifically for Python to manipulate MongoDB, making stir-frying easy and useful.

Let’s finish the Json part first.

Return implementation in Json format

We’re going to implement the get() method in JsonHandler. Here, we first read the data from the database, and then have to convert it to dict() format, because PyMongo can’t convert it directly to Json because it has something called Object_id in it. Dumps ({“data”: {“block”: return_data, “curTime”: cur_time}})). Dumps ({“data”: {“block”: return_data, “cur_time}}) The structure is quite simple, roughly the code is as follows:

 1class JsonHandle(tornado.web.RequestHandler):
 2    def get(self):
 3        Read data from the database
 4        self.client = pymongo.MongoClient("Mongo: / / 39.11.12.123 /", 27017)
 5        self.db = self.client["DailyProject"]
 6        self.table = self.db["table"]
 7        result = self.table.find()
 8        Get the current time
 9        time = datetime.datetime.now()
10        cur_time = str(time.year) + "-" + str(time.month) + "-" + str(time.day)
11        Filter out the right data
12        temp_posts = []
13        posts = []
14        for item in result:
15            temp_posts.append(item)
16            temp_posts.sort(key=lambda k: (k['post_time'][-5:]), reverse=True)
17        for item in temp_posts:
18            if item['post_day_time'] == cur_time:
19                posts.append(item)
20        Convert data to dict() for easy conversion to Json
21        return_data = []
22        for item in posts:
23            temp_dic = {'postId': item['post_id'].'postTitle': item['post_title'],'postPartUrl': item['post_part_url']}
25            return_data.append(temp_dic)
26        Return data in Json format
27        self.write(json.dumps({"data": {"block": return_data, "curTime": cur_tim
Copy the code

Here’s how it looks:





So, isn’t it super cool to implement? Here you implement the GET method, but you can also implement the POST method to handle HTTP POST requests. The specific logic depends on your specific business. Dumps returns json.dumps anyway.

Tip: If you return a json format that is similar, you can pull it out, write a template, and pass the data directly to the template when you return the result. You don’t need to write the JSON format in every method, which can be too costly to modify.

Return implementation of Web format

The Web returns the result, so we’re using the HTML stuff here. First, we need to create an index.html file inside the template. Then, in WebHandler, the final result will be: self.render(“index.html”, info=posts, today=cur_time). Just to be brief, the first argument is the corresponding HTML file in your template. The second and third arguments are the data you need to pass to the front end. Call it whatever you want, but keep it consistent with the HTML.

The code for this Handler looks like this:

 1class WebHandle(tornado.web.RequestHandler):
 2    def get(self):
 3        self.client = pymongo.MongoClient("Mongo: / / 39.11.12.123 /", 27017)
 4        self.db = self.client["DailyProject"]
 5        self.table = self.db["table"]
 6        result = self.table.find()
 7        time = datetime.datetime.now()
 8        cur_time = str(time.year) + "-" + str(time.month) + "-" + str(time.day)
 9        temp_posts = []
10        posts = []
11        for item in result:
12            temp_posts.append(item)
13            temp_posts.sort(key=lambda k: (k['post_time'][-5:]), reverse=True)
14        for item in temp_posts:
15            if item['post_day_time'] == cur_time:
16                posts.append(item)
17        self.render("index.html", info=posts, today=cur_time)
Copy the code

Because the name must correspond to the front end, the front end code is as follows:

1<body> 2 3<h1> Technical discussion {{today}}</h1> 4 5{%for element in info %}
 6<div class="post_block">
 7
 8   <p class="post_id">{{element['post_id']}}</p>
 9      <a class="post_url" href="{{element['post_url']}}" data-url="{{element['post_url']}}" target="_blank">{{element['post_title']}}</a>
10   <p class="post_time">{{element['post_time']}}</p>
11
12</div>
13{% end %}
14
15</body>
Copy the code

Note that the “today” passed by the back end corresponds to {{today}} in the HTML, and the “info” in the for loop. This for loop has a syntax a bit like dot.js. Don’t panic, this front-end writing method is only a few, it is not very difficult to see how to write examples, just follow suit to their own HTML can be written.

See, it’s that simple, and finally we run it like this:



404 page processing

To handle a 404 page, simply add a (r”.*”, BaseHandle) to the url of the main.py file and return a 404. Fried chicken is easy.

Finally very key, how to run up the program!

Finally, the code is written, and we need to get our program running.

First, deploy your project to your server and successfully upload the file using the deployment method described above.

Then, log in to your server and go to the project specified folder.

Since our launcher is written in main.py, we just need to type:

1# sudo python main.py &
Copy the code

Can let your Tornado background run! And don’t forget the ampersand.

To close your running application, type:

1# ps -ef | grep main.py
Copy the code

Find the process you Tornado is in and shut it down with the kill command.

1# kill -9 < process number >
Copy the code

Postscript not postscript

See? That’s it. An example is simple, but there’s a lot that can be extended here. For those of you who don’t know how to write server-side code, this article is a good way to get started and take a small step forward, because it’s not just hello World.

We also mentioned that Tornado can be used to execute tasks regularly, but I won’t talk about it here. If you want to communicate more, please pay attention to “Pikepa’s poop shovel officer” and click “Enter group communication” below to discuss in the group.

These content code, I also give you to share out, the same is to follow the “pikepa shovel shit officer”, reply “Tornado”, you can get the download address.

Finally, I would like to make fun of the article of reptile. It is enough for you to read one article, because the reptile is really not a real technical work, and it can not reflect your technology at all. Frankly, it is a tool. It’s not very technical. All that crawling around, crawling around, crawling around, crawling around, crawling around, crawling around, crawling around, crawling around, crawling around, crawling around, crawling around, crawling around, crawling around, crawling around, crawling around, crawling around, crawling around. Because the data it gives you to climb is useless. Unlike my previous crawler, my crawler, I tell you the idea, and my crawler is actually running on the server.
Crawlers are about providing data, not some fancy technology, rightAnd the jobs, the crawlers are ready-made, it’s not your turn to write.

Recommended reading

This is how you’re going to get to the top of your game and get to the top of your game. This is how you’re going to get to the top of your game and get to the top of your game and get to the bottom of your game. Use Scrapyd to deploy crawlers step by step on Tencent cloud

So hard goods of the public number, you do not pay attention to it?