mini web框架

文件結(jié)構(gòu)

├── dynamic ---存放py模塊
│   └── my_web.py
├── templates ---存放模板文件
│   ├── center.html
│   ├── index.html
│   ├── location.html
│   └── update.html
├── static ---存放靜態(tài)的資源文件
│   ├── css
│   │   ├── bootstrap.min.css
│   │   ├── main.css
│   │   └── swiper.min.css
│   └── js
│       ├── a.js
│       ├── bootstrap.min.js
│       ├── jquery-1.12.4.js
│       ├── jquery-1.12.4.min.js
│       ├── jquery.animate-colors.js
│       ├── jquery.animate-colors-min.js
│       ├── jquery.cookie.js
│       ├── jquery-ui.min.js
│       ├── server.js
│       ├── swiper.jquery.min.js
│       ├── swiper.min.js
│       └── zepto.min.js
└── web_server.py ---mini web服務(wù)器

my_web.py

import time
import os
import re

template_root = "./templates"


def index(file_name):
    """返回index.py需要的頁面內(nèi)容"""
    # return "hahha" + os.getcwd()  # for test 路徑問題
    try:
        file_name = file_name.replace(".py", ".html")
        f = open(template_root + file_name)
    except Exception as ret:
        return "%s" % ret
    else:
        content = f.read()
        f.close()

        # --------更新-------
        data_from_mysql = "數(shù)據(jù)還沒有敬請期待...."
        content = re.sub(r"\{%content%\}", data_from_mysql, content)

        return content


def center(file_name):
    """返回center.py需要的頁面內(nèi)容"""
    # return "hahha" + os.getcwd()  # for test 路徑問題
    try:
        file_name = file_name.replace(".py", ".html")
        f = open(template_root + file_name)
    except Exception as ret:
        return "%s" % ret
    else:
        content = f.read()
        f.close()

        # --------更新-------
        data_from_mysql = "暫時沒有數(shù)據(jù),,,,~~~~(>_<)~~~~ "
        content = re.sub(r"\{%content%\}", data_from_mysql, content)

        return content

def application(environ, start_response):
    status = '200 OK'
    response_headers = [('Content-Type', 'text/html')]
    start_response(status, response_headers)

    file_name = environ['PATH_INFO']
    if file_name == "/index.py":
        return index(file_name)
    elif file_name == "/center.py":
        return center(file_name)
    else:
        return str(environ) + '==Hello world from a simple WSGI application!--->%s\n' % time.ctime()

web_server.py

import select
import time
import socket
import sys
import re
import multiprocessing

class WSGIServer(object):
    """定義一個WSGI服務(wù)器的類"""

    def __init__(self, port, documents_root, app):

        # 1\. 創(chuàng)建套接字
        self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        # 2\. 綁定本地信息
        self.server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        self.server_socket.bind(("", port))
        # 3\. 變?yōu)楸O(jiān)聽套接字
        self.server_socket.listen(128)

        # 設(shè)定資源文件的路徑
        self.documents_root = documents_root

        # 設(shè)定web框架可以調(diào)用的函數(shù)(對象)
        self.app = app

    def run_forever(self):
        """運行服務(wù)器"""

        # 等待對方鏈接
        while True:
            new_socket, new_addr = self.server_socket.accept()
            # 創(chuàng)建一個新的進程來完成這個客戶端的請求任務(wù)
            new_socket.settimeout(3)  # 3s
            new_process = multiprocessing.Process(target=self.deal_with_request, args=(new_socket,))
            new_process.start()
            new_socket.close()

    def deal_with_request(self, client_socket):
        """以長鏈接的方式雌桑,為這個瀏覽器服務(wù)器"""

        while True:
            try:
                request = client_socket.recv(1024).decode("utf-8")
            except Exception as ret:
                print("========>", ret)
                client_socket.close()
                return

            # 判斷瀏覽器是否關(guān)閉
            if not request:
                client_socket.close()
                return

            request_lines = request.splitlines()
            for i, line in enumerate(request_lines):
                print(i, line)

            # 提取請求的文件(index.html)
            # GET /a/b/c/d/e/index.html HTTP/1.1
            ret = re.match(r"([^/]*)([^ ]+)", request_lines[0])
            if ret:
                print("正則提取數(shù)據(jù):", ret.group(1))
                print("正則提取數(shù)據(jù):", ret.group(2))
                file_name = ret.group(2)
                if file_name == "/":
                    file_name = "/index.html"

            # 如果不是以py結(jié)尾的文件逊朽,認(rèn)為是普通的文件
            if not file_name.endswith(".py"):

                # 讀取文件數(shù)據(jù)
                try:
                    f = open(self.documents_root+file_name, "rb")
                except:
                    response_body = "file not found, 請輸入正確的url"

                    response_header = "HTTP/1.1 404 not found\r\n"
                    response_header += "Content-Type: text/html; charset=utf-8\r\n"
                    response_header += "Content-Length: %d\r\n" % (len(response_body))
                    response_header += "\r\n"

                    response = response_header + response_body

                    # 將header返回給瀏覽器
                    client_socket.send(response.encode('utf-8'))

                else:
                    content = f.read()
                    f.close()

                    response_body = content

                    response_header = "HTTP/1.1 200 OK\r\n"
                    response_header += "Content-Length: %d\r\n" % (len(response_body))
                    response_header += "\r\n"

                    # 將header返回給瀏覽器
                    client_socket.send(response_header.encode('utf-8') + response_body)

            # 以.py結(jié)尾的文件衬以,就認(rèn)為是瀏覽需要動態(tài)的頁面
            else:
                # 準(zhǔn)備一個字典,里面存放需要傳遞給web框架的數(shù)據(jù)
                env = dict()
                # 存web返回的數(shù)據(jù)
                response_body = self.app(env, self.set_response_headers)

                # 合并header和body
                response_header = "HTTP/1.1 {status}\r\n".format(status=self.headers[0])
                response_header += "Content-Type: text/html; charset=utf-8\r\n"
                response_header += "Content-Length: %d\r\n" % len(response_body)
                for temp_head in self.headers[1]:
                    response_header += "{0}:{1}\r\n".format(*temp_head)

                response = response_header + "\r\n"
                response += response_body

                client_socket.send(response.encode('utf-8'))

    def set_response_headers(self, status, headers):
        """這個方法,會在 web框架中被默認(rèn)調(diào)用"""
        response_header_default = [
            ("Data", time.time()),
            ("Server", "ItCast-python mini web server")
        ]

        # 將狀態(tài)碼/相應(yīng)頭信息存儲起來
        # [字符串, [xxxxx, xxx2]]
        self.headers = [status, response_header_default + headers]

# 設(shè)置靜態(tài)資源訪問的路徑
g_static_document_root = "./static"
# 設(shè)置動態(tài)資源訪問的路徑
g_dynamic_document_root = "./dynamic"

def main():
    """控制web服務(wù)器整體"""
    # python3 xxxx.py 7890
    if len(sys.argv) == 3:
        # 獲取web服務(wù)器的port
        port = sys.argv[1]
        if port.isdigit():
            port = int(port)
        # 獲取web服務(wù)器需要動態(tài)資源時腌逢,訪問的web框架名字
        web_frame_module_app_name = sys.argv[2]
    else:
        print("運行方式如: python3 xxx.py 7890 my_web_frame_name:application")
        return

    print("http服務(wù)器使用的port:%s" % port)

    # 將動態(tài)路徑即存放py文件的路徑芒划,添加到path中,這樣python就能夠找到這個路徑了
    sys.path.append(g_dynamic_document_root)

    ret = re.match(r"([^:]*):(.*)", web_frame_module_app_name)
    if ret:
        # 獲取模塊名
        web_frame_module_name = ret.group(1)
        # 獲取可以調(diào)用web框架的應(yīng)用名稱
        app_name = ret.group(2)

    # 導(dǎo)入web框架的主模塊
    web_frame_module = __import__(web_frame_module_name)
    # 獲取那個可以直接調(diào)用的函數(shù)(對象)
    app = getattr(web_frame_module, app_name) 

    # print(app)  # for test

    # 啟動http服務(wù)器
    http_server = WSGIServer(port, g_static_document_root, app)
    # 運行http服務(wù)器
    http_server.run_forever()

if __name__ == "__main__":
    main()
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末蚤蔓,一起剝皮案震驚了整個濱河市卦溢,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌秀又,老刑警劉巖单寂,帶你破解...
    沈念sama閱讀 211,290評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異吐辙,居然都是意外死亡宣决,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,107評論 2 385
  • 文/潘曉璐 我一進店門袱讹,熙熙樓的掌柜王于貴愁眉苦臉地迎上來疲扎,“玉大人,你說我怎么就攤上這事捷雕〗飞ィ” “怎么了?”我有些...
    開封第一講書人閱讀 156,872評論 0 347
  • 文/不壞的土叔 我叫張陵救巷,是天一觀的道長壶熏。 經(jīng)常有香客問我,道長浦译,這世上最難降的妖魔是什么棒假? 我笑而不...
    開封第一講書人閱讀 56,415評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮精盅,結(jié)果婚禮上帽哑,老公的妹妹穿的比我還像新娘。我一直安慰自己叹俏,他們只是感情好妻枕,可當(dāng)我...
    茶點故事閱讀 65,453評論 6 385
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著粘驰,像睡著了一般屡谐。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上蝌数,一...
    開封第一講書人閱讀 49,784評論 1 290
  • 那天愕掏,我揣著相機與錄音,去河邊找鬼顶伞。 笑死饵撑,一個胖子當(dāng)著我的面吹牛剑梳,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播肄梨,決...
    沈念sama閱讀 38,927評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼阻荒,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了众羡?” 一聲冷哼從身側(cè)響起侨赡,我...
    開封第一講書人閱讀 37,691評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎粱侣,沒想到半個月后羊壹,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,137評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡齐婴,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,472評論 2 326
  • 正文 我和宋清朗相戀三年油猫,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片柠偶。...
    茶點故事閱讀 38,622評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡情妖,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出诱担,到底是詐尸還是另有隱情毡证,我是刑警寧澤,帶...
    沈念sama閱讀 34,289評論 4 329
  • 正文 年R本政府宣布蔫仙,位于F島的核電站料睛,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏摇邦。R本人自食惡果不足惜恤煞,卻給世界環(huán)境...
    茶點故事閱讀 39,887評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望施籍。 院中可真熱鬧居扒,春花似錦、人聲如沸丑慎。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽立哑。三九已至,卻和暖如春姻灶,著一層夾襖步出監(jiān)牢的瞬間铛绰,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工产喉, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留捂掰,地道東北人敢会。 一個月前我還...
    沈念sama閱讀 46,316評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像这嚣,于是被迫代替她去往敵國和親鸥昏。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,490評論 2 348

推薦閱讀更多精彩內(nèi)容