[零基礎學python]Hello,第一個網頁分析

As he walked by the sea of Galilee, he saw two brothers, Simon, who is called Peter, and Andrew his brother, casting a net into the sea--for they were fishermen. And he said to them,"Follow me, and I will make you fish for people." Immediately they left their nets and followed him.(MATTHEW 5:18-20)html

打開文本編輯器。這裏要說一下啦,理論上講,全部的文本編輯器均可以作爲編寫程序的工具。前面已經提到的那個python IDE,是一個很好的工具,再有別的也行,好比我就用vim(好像個人計算機只能用vim了,上次運行Libre Office都很慢,敲一個鍵以後喝口水,纔看到那個字母出來,等有人資助我了,也搞一個蘋果的什麼機器玩玩。)。用什麼編輯工具,全是本身的喜歡罷了,不用爭論那個好,這個差,只要本身順手便可。python

把下面的代碼原封不動地複製過去,而且保存爲文件名是hello.py的文件,存到那個目錄中,本身選好了。git

#!/usr/bin/env python
#coding:utf-8

import tornado.httpserver
import tornado.ioloop
import tornado.options
import tornado.web

from tornado.options import define, options
define("port", default=8000, help="run on the given port", type=int)

class IndexHandler(tornado.web.RequestHandler):
    def get(self):
        greeting = self.get_argument('greeting', 'Hello')
        self.write(greeting + ', welcome you to read: www.itdiffer.com')

if __name__ == "__main__":
    tornado.options.parse_command_line()
    app = tornado.web.Application(handlers=[(r"/", IndexHandler)])
    http_server = tornado.httpserver.HTTPServer(app)
    http_server.listen(options.port)
    tornado.ioloop.IOLoop.instance().start()

進入到保存hello.py文件的目錄,在shell或者命令輸入框(windows能夠用cmd)中,輸入:github

qw@qw-Latitude-E4300:~/codes$ python hello.py

用python運行這個文件,其實就已經發布了一個網站,只不過這個網站太簡單了。web

接下來,打開瀏覽器,在瀏覽器中輸入:http://localhost:8000,獲得以下界面:正則表達式

圖片描述

固然,若是還能夠在shell中用下面方式運行:shell

qw@qw-Latitude-E4300:~$ curl http://localhost:8000/
Hello, welcome you to read: www.itdiffer.com 

qw@qw-Latitude-E4300:~$ curl http://localhost:8000/?greeting=Qiwsir
Qiwsir, welcome you to read: www.itdiffer.com

若是你的全部操做都正確,必定可以看到上面的結果。json

恭喜你,邁出了決定性一步,已經能夠用Tornado發佈網站了。在這裏彷佛沒有作什麼部署,只是安裝了Tornado。是的,不須要如同部署Nginx或者Apache那樣,作各類設置了,由於Tornado就是一個很好的server,也是一個開發框架。vim

上面代碼雖然跑起來了,可是每行都什麼意思呢?下面就逐行解釋,也就理解了Tornado這個框架的基本結構和用法。windows

WEB服務器工做流程

任何一個網站都離不開Web服務器,這裏所說的不是指那個更計算機同樣的硬件設備,是指裏面安裝的軟件,有時候初次接觸的看官容易搞混。就來偉大的維基百科都這麼說

有時,這兩種定義會引發混淆,如Web服務器。它多是指用於網站的計算機,也多是指像Apache這樣的軟件,運行在這樣的計算機上以管理網頁組件和迴應網頁瀏覽器的請求。

在具體的語境中,看官要注意分析,到底指的是什麼。

關於Web服務器比較好的解釋,推薦看看百度百科的內容,我這裏就不復制粘貼了,具體能夠點擊鏈接查閱:WEB服務器

在WEB上,用的最多的就是輸入網址,訪問某個網站。全世界那麼多網站網頁,若是去訪問他們,怎麼可以作到彼此互通互聯呢。爲了協調彼此,就制定了不少通用的協議,其中http協議,就是網絡協議中的一種。關於這個協議的介紹,網上隨處就能找到,請看官本身google.

網上偷來的一張圖(從哪裏偷來的,我都告訴你了,多實在呀。哈哈。),顯示在下面,簡要說明web服務器的工做過程

圖片描述

偷個完全,把原文中的說明也貼上:

  1. 建立listen socket, 在指定的監聽端口, 等待客戶端請求的到來
  2. listen socket接受客戶端的請求, 獲得client socket, 接下來經過client socket與客戶端通訊
  3. 處理客戶端的請求, 首先從client socket讀取http請求的協議頭, 若是是post協議, 還可能要讀取客戶端上傳的數據, 而後處理請求, 準備好客戶端須要的數據, 經過client socket寫給客戶端

剽竊就此結束,下面就本身寫了。

引入模塊

import tornado.httpserver
import tornado.ioloop
import tornado.options
import tornado.web

這四個都是Tornado的模塊,在本例中都是必須的。它們四個在通常的網站開發中,都要用到,基本做用分別是:

  • tornado.httpserver:這個模塊就是用來解決web服務器的http協議問題,它提供了很多屬性方法,實現客戶端和服務器端的互通。Tornado的非阻塞、單線程的特色在這個模塊中體現。
  • tornado.ioloop:這個也很是重要,可以實現非阻塞socket循環,不能互通以此就結束呀。
  • tornado.options:這是命令行解析模塊,也經常使用到。
  • tornado.web:這是必不可少的模塊,它提供了一個簡單的Web框架與異步功能,從而使其擴展到大量打開的鏈接,使其成爲理想的長輪詢。

還有一個模塊引入,是用from...import完成的

from tornado.options import define, options
define("port", default=8000, help="run on the given port", type=int)

這兩句就顯示了所謂「命令行解析模塊」的用途了。在這裏經過tornado.options.define()定義了訪問本服務器的端口,就是當在瀏覽器地址欄中輸入http:localhost:8000的時候,才能訪問本網站,由於http協議默認的端口是80,爲了區分,我在這裏設置爲8000,爲何要區分呢?由於個人計算機或許你的也是,已經部署了別的注入Nginx服務器了,它的端口是80,因此要區分開,而且,後面咱們還會將tornado和Nginx聯合起來工做,這樣兩個服務器在同一臺計算機上,就要分開嘍。

定義請求-處理程序類

class IndexHandler(tornado.web.RequestHandler):
    def get(self):
        greeting = self.get_argument('greeting', 'Hello')
        self.write(greeting + ', welcome you to read: www.itdiffer.com')

所謂「請求處理」程序類,就是要定義一個類,專門應付客戶端向服務器提出請求(這個請求也許是要讀取某個網頁,也許是要將某些信息存到服務器上),服務器要有相應的程序來接收並處理這個請求,而且反饋某些信息(或者是針對請求反饋所要的信息,或者返回其它的錯誤信息等)。

因而,就定義了一個類,名字是IndexHandler,固然,名字能夠隨便取了,可是,按照習慣,類的名字中的單詞首字母都是大寫的,而且若是這個類是請求處理程序類,那麼就最好用Handler結尾,這樣在名稱上很明確,是幹什麼的。

類IndexHandler的參數是tornado.web.RequestHandler,這個參數很重要,是專門用於完成請求處理程序的,經過它定義get()post()兩個在web中應用最多的方法的內容(關於這兩個方法的詳細解釋,能夠參考:HTTP GET POST的本質區別詳解,做者在這篇文章中,闡述了兩個方法的本質)。

在本例中,只定義了一個get()方法。請看官注意,類中的方法能夠沒有別的參數,可是必須有self這個參數,關於這點請參與前面幾篇關於類的講授內容(返回首頁找相關文章)。

greeting = self.get_argument('greeting', 'Hello')這句中,當實例化以後,self對應的就是tornado.web.RequestHandler,而get_argument則是tornado.web.RequestHandler的一個方法。官方文檔對這個方法的描述以下:

RequestHandler.get_argument(name, default=, []strip=True)

Returns the value of the argument with the given name.

If default is not provided, the argument is considered to be required, and we raise a MissingArgumentError if it is missing.

If the argument appears in the url more than once, we return the last value.

The returned value is always unicode.

這段描述已經很清晰了,此外,看完這段說明,看官是否明白我在前面運行的:

qw@qw-Latitude-E4300:~$ curl http://localhost:8000/?greeting=Qiwsir
Qiwsir, welcome you to read: www.itdiffer.com

爲何經過http://localhost:8000/?greeting=Qiwsir,就能夠實現對greeting的賦值。

接下來的那句self.write(greeting + ',weblcome you to read: www.itdiffer.com)'中,write也是tornado.web.RequestHandler的一個方法,這發方法主要功能是向客戶端反饋參數中的信息。也瀏覽一下官方文檔信息,對之後正確理解使用有幫助:

RequestHandler.write(chunk)[source]

Writes the given chunk to the output buffer.

To write the output to the network, use the flush() method below.

If the given chunk is a dictionary, we write it as JSON and set the Content-Type of the response to be application/json. (if you want to send JSON as a different Content-Type, call set_header after calling write()).

main()方法

if __name__ == "__main__",從這句話開始執行編寫的程序,前面至關於預備工做吧。這個方法跟以往執行python程序是同樣的。

tornado.options.parse_command_line(),這是在執行tornado的解析命令行。在tornado的程序中,只要import模塊以後,就會在運行的時候自動加載,不須要了解細節,可是,在main()方法中若是有命令行解析,必需要提早將模塊引入。

Application類

下面這句是重點:

app = tornado.web.Application(handlers=[(r"/", IndexHandler)])

將tornado.web.Application實例化。這個實例化,本質上是創建了整個網站程序的請求處理集合,而後它能夠被HTTPServer作爲參數調用,實現http協議服務器訪問。Application類的__init__方法參數形式:

def __init__(self, handlers=None, default_host="", transforms=None,**settings):
    pass

在通常狀況下,handlers是不能爲空的,由於Application類經過這個參數的值處理所獲得的請求。例如在本例中,handlers=[(r"/", IndexHandler)],就意味着若是經過瀏覽器的地址欄輸入根路徑(http://localhost:8000就是根路徑,若是是http://localhost:8000/qiwsir,就不屬於根,而是一個子路徑或目錄了),對應這就是讓名字爲IndexHandler類處理這個請求。

經過handlers傳入的數值格式,必定要注意,在後面作複雜結構的網站是,這裏就顯得重要了。它一個list,list裏面的參數是列表,列表的組成包括兩部分,一部分是請求路徑,另一部分是處理程序的類名稱。注意請求路徑能夠用正則表達式書寫。舉例說明:

handlers = [
    (r"/", IndexHandlers),              #來自根路徑的請求用IndesHandlers處理
    (r"/qiwsir/(.*)", QiwsirHandlers),  #來自/qiwsir/以及其下任何請求(正則表達式表示任何字符)都由QiwsirHandlers處理
]

注意

在這裏我使用了r"/"的樣式,意味着就不須要使用轉義符,r後面的都表示該符號原本的含義。例如,\n,若是單純這麼來使用,就覺得着換行,由於符號「\」具備轉義功能(關於轉義詳細閱讀《玩轉字符串(1)》),當寫成r"\n"的形式是,就再也不表示換行了,而是兩個字符,\和n,不會轉意。通常狀況下,因爲正則表達式和 \ 會有衝突,所以,當一個字符串使用了正則表達式後,最好在前面加上'r'。(關於正則表達式,看官姑且網上搜索,在後面的課程中,我也會介紹)

關於Application類的介紹,告一段落,可是並未徹底講述了,由於還有別的參數設置沒有講,看官有興趣能夠閱讀官方的文檔資料,地址是:http://tornado.readthedocs.org/en/latest/_modules/tornado/web.html#Application

HTTPServer類

實例化以後,Application對象(用app作爲標籤的)就能夠被另一個類HTTPServer引用,形式爲:

http_server = tornado.httpserver.HTTPServer(app)

HTTPServer是tornado.httpserver裏面定義的類。HTTPServer是一個單線程非阻塞HTTP服務器,執行HTTPServer通常要回調Application對象,並提供發送響應的接口,也就是下面的內容是跟隨上面語句的(options.port的值在IndexHandler類前面經過from...import..設置的)。

http_server.listen(options.port)

這種方法,就創建了單進程的http服務。

請看官牢記,若是在之後編碼中,遇到須要多進程,請參考官方文檔說明:http://tornado.readthedocs.org/en/latest/httpserver.html#http-server

IOLoop類

剩下最後一句了:

tornado.ioloop.IOLoop.instance().start()

這句話,老是在__main()__的最後一句。表示能夠接收來自HTTP的請求了。

以上把一個簡單的hello.py剖析。想必讀者對Tornado編寫網站的基本概念已經有了。


首頁   |   上一講:PYthon框架

相關文章
相關標籤/搜索