Featured image of post Python系列:建立簡單的伺服器

Python系列:建立簡單的伺服器

使用 http.serverflask 套件

伺服器(server)根據維基百科定義,為提供服務的電腦軟體,根據軟體種類可分為:

  • 檔案伺服器: NAS儲存裝置…
  • 網頁伺服器: Apache…
  • 資料庫伺服器: MySQL, MongoDB…

建置正式的伺服器需要諸多考量和維護;如果想檢查網頁專案的目前成果,或簡單分享電腦資源給其他協作者的話,可以透過python建立臨時的網頁伺服器。

在指定目錄內包含index.html就能預覽網頁,若沒有則會顯示當前資料夾結構。以下使用 http.server 模組建立靜態網頁伺服器

http.server 產生靜態伺服器

注意:Python2 和 Python3 使用的模組不同,這裡介紹的為適用於Python3套件與使用方式

下載並引入套件

1
2
3
pip install httpserver
import http.server
from http.server import SimpleHTTPRequestHandler, HTTPServer

還需多引入兩個物件: SimpleHTTPRequestHandlerHTTPServer 下面會簡單介紹他們的功能

最簡單的建置伺服器程式碼

1
2
3
4
5
## example code to create and run the server from python docs
def run(server_class=HTTPServer, handler_class=BaseHTTPRequestHandler):
     server_address = ('', 8000)
     httpd = server_class(server_address, handler_class)
     httpd.serve_forever()

HTTPServer 和 SimpleHTTPRequestHandler

HTTPServer 為socketserver.TCPServer的子類別,能建立一個伺服器實例 還需要給個 RequestHandlerClass 向HTTP提出請求與回應,有以下三種:

  • BaseHTTPRequestHandler
  • SimpleHTTPRequestHandler: 讀取與發佈當前目錄 (比較多人用此object)
  • CGIHTTPRequestHandler 最後給個協定版本(protocol)
1
2
3
HandlerClass = SimpleHTTPRequestHandler
ServerClass  = HTTPServer
Protocol     = "HTTP/1.0"

輸入伺服器相關資訊,包含ip位址,指定port(預設8000)等,並存為httpd變數

1
2
3
4
5
6
7
8
9
if sys.argv[1:]:
  port = int(sys.argv[1])
else:
  port = 8000
server_address = ('127.0.0.1', port)
HandlerClass.protocol_version = Protocol

## standard formula: ip + port + handlerclass
httpd = ServerClass(server_address, HandlerClass)

實體化與運作伺服器 serve_forever()可以透過 shutdown() 關閉

1
2
3
sa = httpd.socket.getsockname() ## ('127.0.0.1' 8000)
print ("Serving HTTP on", sa[0], "port", sa[1], "...")
httpd.serve_forever()

console 顯示 GET … 200 代表請求成功

1
2
Serving HTTP on 127.0.0.1 port 8000 ...
127.0.0.1 - - "GET / HTTP/1.1" 200 -

最後打開瀏覽器,輸入 http://127.0.0.1:8000/ 或是 http://${your_ip}:8000/ 就可看到成果了

完整 code

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# pip install httpserver
import sys
import http.server
from  http.server import SimpleHTTPRequestHandler, HTTPServer

HandlerClass = SimpleHTTPRequestHandler
ServerClass  = HTTPServer
Protocol     = "HTTP/1.0"

if sys.argv[1:]:
  port = int(sys.argv[1])
else:
  port = 8000
server_address = ('127.0.0.1', port)

HandlerClass.protocol_version = Protocol
httpd = ServerClass(server_address, HandlerClass)

sa = httpd.socket.getsockname() ## ('127.0.0.1' 8000)
print ("Serving HTTP on", sa[0], "port", sa[1], "...")
httpd.serve_forever()

## it will print 127.0.0.1 - - "GET / HTTP/1.1" 200 - on console
## <-> to shutdown()

觀看結果

可以拿之前寫的 index.html 放在指定路徑,透過 httpserver 產生 localhost 以觀看 html 成果,若沒有 html 檔則會顯示本機資料夾路徑,可以透過這個方式,分享連結網址給別人以分享資料夾內容

動態伺服器與網路框架

網頁包含動態資訊如資料庫串接,自定義的網頁跳轉等,可利用python flask 達成。此模組提供伺服器端的網頁框架,協助高效率架設網站。

下載與引入套件

這裡先引入最基本的 Flask 其他常用函數(redirect, url_for, send_from_directory...)會在後面介紹

1
2
#pip install Flask
from flask import Flask 

簡單的範例

  • create app.py
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# save this as app.py
from flask import Flask

app = Flask(__name__)

@app.route("/")
def hello():
    return "Hello, World!"
    
if __name__ == '__main__':
    app.debug = True ## not shown in formal case
    app.run()
  • app.py 同層路徑下執行 flask run flask 會生成網頁於 http://127.0.0.1:5000/

名詞和概念筆記

  • flask 內含有 httpserver,但僅適合測試用,正式發布會建議用 WSGI server
  • 裝飾器(decorator): @app.route 做為路由,紀錄 URL/HTTP動作 與其對應的處理函式
    • @app.route('/') 這裡的 / 代表 http://127.0.0.1:5000/ 這個URL
    • 若連結到此網址,會執行 hello() 函數並在網頁印出 Hello, World!
    • 若今天還有其他路由如下,打開 http://127.0.0.1:5000/page/5 就會看到函式執行結果
    1
    2
    3
    
    app.route('/page/5')
    def welcome():
    return "Welcome"
    
  • flask 可以吃URL變數,方法為 <variable_name>

flask 函式 url_for redirect

url_for() 可以讓路由具有追蹤彈性,並搭配 redirect() 跳轉網頁 下面例子可知: http://127.0.0.1:5000/b 會被引導回 http://127.0.0.1:5000/

1
2
3
4
5
6
7
8
from flask import url_for, redirect
@app.route('/')
def hello():
    return 'hello'
    
@app.route('/b')
def b():
    return redirect(url_for('hello'))

其他套件如結合 html css 模板的render_template,或是上傳下載檔案的 send_from_directory 會在下篇介紹我的side project時補上~

References

https://docs.python.org/3/library/http.server.html# https://chwang12341.medium.com/coding%E8%B5%B7%E4%BE%86-python-%E4%B8%80%E8%A1%8C%E6%8C%87%E4%BB%A4%E5%B0%B1%E8%83%BD%E8%BC%95%E9%AC%86%E5%BB%BA%E7%AB%8B%E7%B6%B2%E9%A0%81%E4%BC%BA%E6%9C%8D%E5%99%A8-simplehttpserver%E5%A5%97%E4%BB%B6-http-server%E4%BD%BF%E7%94%A8%E6%95%99%E5%AD%B8-34c30b81c26 https://hackmd.io/@peterju/B18gmJ7Ph#15Flask-%E7%B6%B2%E9%A0%81%E6%A1%86%E6%9E%B6 https://medium.com/@charming_rust_oyster_221/%E4%BD%BF%E7%94%A8-flask-%E5%89%B5%E5%BB%BA-web-api-%E7%AD%86%E8%A8%98-b5618543632e https://medium.com/@charming_rust_oyster_221/flask-%E6%AA%94%E6%A1%88%E4%B8%8A%E5%82%B3%E5%88%B0%E4%BC%BA%E6%9C%8D%E5%99%A8%E7%9A%84%E6%96%B9%E6%B3%95-1-c11097c23137 https://hackmd.io/@shaoeChen/HJiZtEngG/https%3A%2F%2Fhackmd.io%2Fs%2FSyP4YEnef

Licensed under CC BY-NC-SA 4.0
comments powered by Disqus