python 你的第一個網(wǎng)站

2021-09-15 14:58 更新

練習(xí)50.你的第一個網(wǎng)站

最后的3個練習(xí)將會很難,你需要在他們身上多花一些時間。第一個練習(xí)里你將創(chuàng)建一個簡單的web版本的游戲。在你開始這節(jié)練習(xí)以前,你必須已經(jīng)成功地完成過了《習(xí)題 46》的內(nèi)容,正確安裝了pip,而且學(xué)會了如何安裝軟件包以及如何創(chuàng)建項(xiàng)目骨架。如果你不記得這些內(nèi)容,就回到《習(xí)題 46》重新復(fù)習(xí)一遍。

安裝 lpthw.web

在創(chuàng)建你的第一個網(wǎng)頁應(yīng)用程序之前,你需要安裝一個“Web 框架”,它的名字叫lpthw.web。所謂的“框架”通常是指“讓某件事情做起來更容易的軟件包”。在網(wǎng)頁應(yīng)用的世界里,人們創(chuàng)建了各種各樣的“網(wǎng)頁框架”,用來解決他們在創(chuàng)建網(wǎng)站時碰到的問題,然后把這些解決方案用軟件包的方式發(fā)布出來,這樣你就可以利用它們引導(dǎo)創(chuàng)建你自己的項(xiàng)目了。

可選的框架類型有很多很多,不過在這里我們將使用lpthw.web 框架。你可以先學(xué)會它,等到差不多的時候再去接觸其它的框架,不過 lpthw.web 本身挺不錯的,所以就算你一直使用也沒關(guān)系。

使用pip安裝lpthw.web

$ sudo pip install lpthw.web
[sudo] password for zedshaw:
Downloading/unpacking lpthw.web
  Running setup.py egg_info for package lpthw.web

Installing collected packages: lpthw.web
  Running setup.py install for lpthw.web

Successfully installed lpthw.web
Cleaning up...

以上是 Linux 和 Mac OSX 系統(tǒng)下的安裝命令,如果你使用的是 Windows,那你只要把sudo去掉就可以了。如果你無法正常安裝,請回到《習(xí)題 46》,確認(rèn)自己學(xué)會了里邊的內(nèi)容。

Warning:其他 Python 程序員會警告你說lpthw.web只是另外一個叫做web.py的 Web 框架的代碼分支(fork),而web.py又包含了太多的“魔法(magic)”在里邊。如果他們這么說的話,你告訴他們Google App Engine最早用的就是 web.py,但沒有一個 Python 程序員抱怨過它里邊包含了太多的魔法,因?yàn)?Google 用它也沒啥問題。如果Google覺得它可以,那它對你來說也不會差。所以還是回去繼續(xù)學(xué)習(xí)吧,他們這些說法與其說是教導(dǎo)你,不如說是拿他們自己的教條束縛你,你還是忽略這些說法好了。

寫一個簡單的“Hello World”項(xiàng)目

現(xiàn)在我們使用lpthw.web做一個非常簡單的“Hello World”項(xiàng)目出來,首先你要創(chuàng)建一個項(xiàng)目目錄:

$ cd projects
$ mkdir gothonweb
$ cd gothonweb
$ mkdir bin gothonweb tests docs templates
$ touch gothonweb/__init__.py
$ touch tests/__init__.py

你最終的目的是把《習(xí)題43》中的游戲做成一個web應(yīng)用,所以你的項(xiàng)目名稱叫做gothonweb,不過在此之前,你需要創(chuàng)建一個最基本的 lpthw.web 應(yīng)用,將下面的代碼放到 bin/app.py 中:

import web

urls = (
  '/', 'index'
)

app = web.application(urls, globals())

class index:
    def GET(self):
        greeting = "Hello World"
        return greeting

if __name__ == "__main__":
    app.run()

然后使用下面的方法來運(yùn)行這個 web 程序:

$ python bin/app.py
http://0.0.0.0:8080/

如果你這樣做:

$ cd bin/   # WRONG! WRONG! WRONG!
$ python app.py  # WRONG! WRONG! WRONG!

那么你就錯了。在所有Python項(xiàng)目中,都不會用cd到下一級目錄中去啟動服務(wù),你就在最頂層的目錄啟動服務(wù),這樣所有的系統(tǒng)可以訪問所有的模塊和文件。 去重讀習(xí)題46并理解項(xiàng)目布局和如何使用它。

最后,使用你的網(wǎng)頁瀏覽器,打開 URL http://localhost:8080/,你應(yīng)該看到兩樣?xùn)|西,首先是瀏覽器里顯示了 Hello, world!,然后是你的命令行終端顯示了如下的輸出:

$ python bin/app.py
http://0.0.0.0:8080/
127.0.0.1:59542 - - [13/Jun/2011 11:44:43] "HTTP/1.1 GET /" - 200 OK
127.0.0.1:59542 - - [13/Jun/2011 11:44:43] "HTTP/1.1 GET /favicon.ico" - 404 Not Found

這些是lpthw.web 打印出的 log 信息,從這些信息你可以看出服務(wù)器有在運(yùn)行,而且能了解到程序在瀏覽器背后做了些什么事情。這些信息還有助于你發(fā)現(xiàn)程序的問題。例如在最后一行它告訴你瀏覽器試圖獲取/favicon.ico,但是這個文件并不存在,因此它返回的狀態(tài)碼是 404 Not Found。

到這里,我還沒有講到任何 web 相關(guān)的工作原理,因?yàn)槭紫饶阈枰瓿蓽?zhǔn)備工作,以便后面的學(xué)習(xí)能順利進(jìn)行,接下來的兩節(jié)習(xí)題中會有詳細(xì)的解釋。我會要求你用各種方法把你的 lpthw.web 應(yīng)用程序弄壞,然后再將其重新構(gòu)建起來:這樣做的目的是讓你明白運(yùn)行l(wèi)pthw.web 程序需要準(zhǔn)備好哪些東西.

發(fā)生了什么?

在瀏覽器訪問到你的網(wǎng)頁應(yīng)用程序時,發(fā)生了下面一些事情:

  1. 瀏覽器通過網(wǎng)絡(luò)連接到你自己的電腦,它的名字叫做localhost,這是一個標(biāo)準(zhǔn)稱謂,表示的誰就是網(wǎng)絡(luò)中你自己的這臺計算機(jī),不管它實(shí)際名字是什么,你都可以使用localhost 來訪問。它使用到的網(wǎng)絡(luò)端口是8080。
  2. 連接成功以后,瀏覽器對bin/app.py這個應(yīng)用程序發(fā)出了 HTTP 請求(request),要求訪問 URL /,這通常是一個網(wǎng)站的第一個 URL。
  3. bin/app.py 里,我們有一個列表,里邊包含了 URL 和類的匹配關(guān)系。我們這里只定義了一組匹配,那就是 '/', 'index' 的匹配。它的含義是:如果有人使用瀏覽器訪問 / 這一級目錄,lpthw.web 將找到并加載 class index,從而用它處理這個瀏覽器請求。
  4. 現(xiàn)在 lpthw.web 找到了class index,然后針對這個類的一個實(shí)例調(diào)用了 index.GET 這個方法函數(shù)。該函數(shù)運(yùn)行后返回了一個字符串,以供lpthw.web 將其傳遞給瀏覽器。
  5. 最后lpthw.web 完成了對于瀏覽器請求的處理,將響應(yīng)(response)回傳給瀏覽器,于是你就看到了現(xiàn)在的頁面。

確定你真的弄懂了這些,你需要畫一個流程圖,來理清信息是如何從瀏覽器傳遞到lpthw.web,再到index.GET,再回到你的瀏覽器的。

修正錯誤

第一步,把第 11 行的greeting變量賦值刪掉,然后刷新瀏覽器。你應(yīng)該會看到一個錯誤頁面,你可以通過這一頁豐富的錯誤信息看出你的程序崩潰的原因是什么。當(dāng)然你已經(jīng)知道出錯的原因是greeting的賦值丟失了,不過 lpthw.web還是會給你一個挺好的錯誤頁面,讓你能找到出錯的具體位置。試試在這個錯誤頁面上做以下操作:

  1. 檢查每一段Local vars輸出(用鼠標(biāo)點(diǎn)擊它們),追蹤里邊提到的變量名稱,以及它們是在哪些代碼文件中用到的。
  2. 閱讀Request Information 一節(jié),看看里邊哪些知識是你已經(jīng)熟悉了的。Request 是瀏覽器發(fā)給你的 gothonweb應(yīng)用程序的信息。這些知識對于日常網(wǎng)頁瀏覽沒有什么用處,但現(xiàn)在你要學(xué)會這些東西,以便寫出 web 應(yīng)用程序來。3.試著把這個小程序的別的位置改錯,探索一下會發(fā)生什么事情。lpthw.web 的會把一些錯誤信息和堆棧跟蹤(stack trace)信息顯示在命令行終端,所以別忘了檢查命令行終端的信息輸出。

創(chuàng)建基本的模板文件

你已經(jīng)試過用各種方法把這個 lpthw.web 程序改錯,不過你有沒有注意到“Hello World”不是一個好 HTML 網(wǎng)頁呢?這是一個 web 應(yīng)用,所以需要一個合適的 HTML 響應(yīng)頁面才對。為了達(dá)到這個目的,下一步你要做的是將“Hello World”以較大的綠色字體顯示出來。

第一步是創(chuàng)建一個templates/index.html文件,內(nèi)容如下:

$def with (greeting)

<html>
    <head>
        <title>Gothons Of Planet Percal #25</title>
    </head>
<body>

$if greeting:
    I just wanted to say <em style="color: green; font-size: 2em;">$greeting</em>.
$else:
    <em>Hello</em>, world!

</body>
</html>

如果你學(xué)過 HTML 的話,這些內(nèi)容你看上去應(yīng)該很熟悉。如果你沒學(xué)過 HTML,那你應(yīng)該去研究一下,試著用 HTML 寫幾個網(wǎng)頁,從而知道它的工作原理。不過我們這里的 HTML 文件其實(shí)是一個“模板(template)”,如果你向模板提供一些參數(shù),lpthw.web 就會在模板中找到對應(yīng)的位置,將參數(shù)的內(nèi)容填充到模板中。例如每一個出現(xiàn) $greeting的位置,$greeting的內(nèi)容都會被替換成對應(yīng)這個變量名的參數(shù)。

為了讓你的bin/app.py處理模板,你需要寫一寫代碼,告訴lpthw.web 到哪里去找到模板進(jìn)行加載,以及如何渲染(render)這個模板,按下面的方式修改你的 app.py:

import web

urls = (
  '/', 'Index'
)

app = web.application(urls, globals())

render = web.template.render('templates/')

class Index(object):
    def GET(self):
        greeting = "Hello World"
        return render.index(greeting = greeting)

if __name__ == "__main__":
    app.run()

特別注意一下render這個新變量名,注意我修改了index.GET 的最后一行,讓它返回了render.index(),并且將greeting 變量作為參數(shù)傳遞給了這個函數(shù)。

改好上面的代碼后,刷新一下瀏覽器中的網(wǎng)頁,你應(yīng)該會看到一條和之前不同的綠色信息輸出。你還可以在瀏覽器中通過“查看源文件(View Source)”看到模板被渲染成了標(biāo)準(zhǔn)有效的 HTML 源代碼。

這么講也許有些太快了,我來詳細(xì)解釋一下模板的工作原理吧:

  1. bin/app.py里面你添加了一個叫做render的新變量,它本身是一個 web.template.render對象。
  2. 你將templates/ 作為參數(shù)傳遞給了這個對象,這樣就讓render 知道了從哪里去加載模板文件。
  3. 在你后面的代碼中,當(dāng)瀏覽器一如既往地觸發(fā)了index.GET 以后,它沒有再返回簡單的greeting字符串,取而代之的是你調(diào)用了 render.index,而且將問候語句作為一個變量傳遞給它。
  4. 這個render_template函數(shù)可以說是一個“魔法函數(shù)”,它看到了你需要的是index.html,于是就跑到templates/目錄下,找到名字為index.html 的文件,然后就把它渲染(render)一遍(叫“轉(zhuǎn)換一遍”也可以)。
  5. templates/index.html文件中,你可以看到初始定義一行中說這個模板需要使用一個叫greeting的參數(shù),這和函數(shù)定義中的格式差不多。另外和 Python 語法一樣,模板文件是縮進(jìn)敏感的,所以要確認(rèn)自己弄對了縮進(jìn)。
  6. 最后,你讓templates/index.html去檢查greeting這個變量,如果這個變量存在的話,就打印出變量的內(nèi)容,如果不存在的話,就會打印出一個默認(rèn)的問候信息。

要深入理解這個過程,你可以修改 greeting 變量以及 HTML 模板的內(nèi)容,看看會有什么效果。然后創(chuàng)建一個叫做templates/foo.html 的模板,并且使用一個新的render.foo()去渲染它。從這個過程你也可以看出, render 調(diào)用的函數(shù)名稱只要跟 templates/下的 .html 文件名匹配到,這個 HTML 模板就可以被渲染到了。

附加題

  1. 閱讀http://webpy.org/ 里邊的文檔,它其實(shí)和lpthw.web 是同一個項(xiàng)目。
  2. 實(shí)驗(yàn)一下你在上述網(wǎng)站看到的所有的東西,包括里邊的代碼示例。
  3. 閱讀以下 HTML5 和 CSS3 相關(guān)的東西,自己練習(xí)著寫幾個 .html.css 文件。
  4. 如果你有一個懂 Django 朋友可以幫你的話,你可以試著使用 Django 完成一下習(xí)題 50、51、52,看看結(jié)果會是什么樣子的。

常見問題

Q: 我好想無法連接到http://localhost:8080/

那么試試訪問http://127.0.0.1:8080/

Q: lpthw.webweb.py有什么區(qū)別?

沒有區(qū)別。我只是在特定版本“鎖定”web.py,以使它對所有學(xué)生都是一樣的,然后再命名為lpthw.web,上一個版本的web.py可能就不同于這一版本。

Q: 我的代碼找不到index.html(或者其他文件)

你可能是先執(zhí)行了cd bin/,不要執(zhí)行這一句,所有的命令都應(yīng)該在bin/的上一級目錄執(zhí)行,所以如果你不能執(zhí)行python bin/app.py,說明你在錯誤的目錄上。

Q: 當(dāng)我們調(diào)用模板的時候,為什么要執(zhí)行greeting=greeting賦值操作

你并沒有給greeting賦值,你只是給模板設(shè)定一個命名參數(shù)。這是聲明的一種,但它只影響調(diào)用模板的功能。

Q: 我的電腦上不能使用8080端口

你可能有一個殺毒程序占用了這個端口,試試別的端口。

Q: 安裝lpthw.web 時,我遇到報錯信息ImportError "No module named web"

你可能安裝了多個版本的Python并且正在使用一個錯誤的版本,或者你是因?yàn)槭褂昧艘粋€舊版本的pip,導(dǎo)致安裝沒有成功,試著先卸載lpthw.web,在重裝一次,如果還沒有解決問題,再次確認(rèn)下你是否使用了正確的Python版本。

以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號