Python的web伺服器

来源:http://www.cnblogs.com/jiaoyu121/archive/2017/06/21/7061679.html
-Advertisement-
Play Games

1.瀏覽器請求動態頁面過程 2.WSGI Python Web Server Gateway Interface (或簡稱 WSGI,讀作“wizgy”)。 WSGI允許開發者將選擇web框架和web伺服器分開。可以混合匹配web伺服器和web框架,選擇一個適合的配對。比如,可以在Gunicorn ...


1.瀏覽器請求動態頁面過程

2.WSGI

Python Web Server Gateway Interface (或簡稱 WSGI,讀作“wizgy”)。

WSGI允許開發者將選擇web框架和web伺服器分開。可以混合匹配web伺服器和web框架,選擇一個適合的配對。比如,可以在Gunicorn 或者 Nginx/uWSGI 或者 Waitress上運行 Django, Flask, 或 Pyramid。真正的混合匹配,得益於WSGI同時支持伺服器和架構.

web伺服器必須具備WSGI介面,所有的現代Python Web框架都已具備WSGI介面,它讓你不對代碼作修改就能使伺服器和特點的web框架協同工作。

WSGI由web伺服器支持,而web框架允許你選擇適合自己的配對,但它同樣對於伺服器和框架開發者提供便利使他們可以專註於自己偏愛的領域和專長而不至於相互牽制。其他語言也有類似介面:java有Servlet API,Ruby 有 Rack。

3.定義WSGI介面

WSGI介面定義非常簡單,它只要求Web開發者實現一個函數,就可以響應HTTP請求。我們來看一個最簡單的Web版本的“Hello World!”:

def application(environ, start_response):
    start_response('200 OK', [('Content-Type', 'text/html')])
    return 'Hello World!'

上面的 application( ) 函數就是符合WSGI標準的一個HTTP處理函數,它接收兩個參數:

  • environ:一個包含所有HTTP請求信息的dict對象;
  • start_response:一個發送HTTP響應的函數。

整個application( )函數本身沒有涉及到任何解析HTTP的部分,也就是說,把底層web伺服器解析部分和應用程式邏輯部分進行了分離,這樣開發者就可以專心做一個領域了.

application( )函數必須由WSGI伺服器來調用。有很多符合WSGI規範的伺服器。而我們此時的web伺服器項目的目的就是做一個極可能解析靜態網頁還可以解析動態網頁的伺服器

實現代碼:

import time,multiprocessing,socket,os,re

class MyHttpServer(object):

    def __init__(self):
        serveSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.serveSocket = serveSocket
        self.HTMLPATH = './html'

    def bind(self,port=8000):
        self.serveSocket.bind(('',port))

    def start(self):
        self.serveSocket.listen()
        while True:
            clientSocket, clientAddr = self.serveSocket.accept()
            print(clientSocket)
            multiprocessing.Process(target=self.serveHandler, args=(clientSocket, clientAddr)).start()
            clientSocket.close()

    def serveHandler(self,clientSocket,clientAddr):
        try:
            recvData = clientSocket.recv(1024).decode('gbk')
            fileName = re.split(r' +', recvData.splitlines()[0])[1]
            filePath = self.HTMLPATH

            if fileName.endswith('.py'):
                try:
                    pyname=fileName[1:-3]
                    # 導入
                    pyModule = __import__(pyname)

                    env={}
                    responseBody = pyModule.application(env,self.startResponse)
                    responseLine = self.responseLine
                    responseHeader = self.responseHeader
                except ImportError:
                    responseLine = 'HTTP/1.1 404 NOT FOUND'
                    responseHeader = 'Server: ererbai' + os.linesep
                    responseHeader += 'Date: %s' % time.ctime()
                    responseBody = '<h1>很抱歉,伺服器中找不到你想要的內容<h1>'
            else:
                if '/'== fileName:
                    filePath += '/index.html'
                else:
                    filePath += fileName

                try:
                    file = None
                    file =open(filePath,'r',encoding='gbk')
                    responseBody = file.read()

                    responseLine = 'HTTP/1.1 200 OK'
                    responseHeader = 'Server: ererbai' + os.linesep
                    responseHeader += 'Date:%s' % time.ctime()
                except FileNotFoundError:
                    responseLine = 'HTTP/1.1 404 NOT FOUND'
                    responseHeader = 'Server: ererbai' + os.linesep
                    responseHeader += 'Date:%s' % time.ctime()
                    responseBody = '很抱歉,伺服器中找不到你想要的內容'


                finally:
                    if (file!=None) and (not file.closed):
                        file.close()

        except Exception as ex:
            responseLine = 'HTTP/1.1 500 ERROR'
            responseHeader = 'Server: ererbai' + os.linesep
            responseHeader += 'Date: %s' % time.ctime()
            responseBody = '伺服器正在維護中,請稍後再試。%s'%ex
        finally:
            senData = responseLine + os.linesep + responseHeader + os.linesep + os.linesep + responseBody
            print(senData)
            senData = senData.encode('gbk')
            clientSocket.send(senData)
            if (clientSocket!=None) and ( not clientSocket._closed):
                clientSocket.close()

    def startResponse(self,status,responseHeaders):
        self.responseLine = status
        self.responseHeader = ''
        for k,v in responseHeaders:
            kv = k + ':' + v + os.linesep
            self.responseHeader += kv



if __name__ == '__main__':
    server = MyHttpServer()
    server.bind(8000)
    server.start()

伺服器中存在的html的文件:

  • index.html
<html>
<head>
    <title>首頁-畢業季</title>
    <meta http-equiv=Content-Type content="text/html;charset=gbk">

</head>
<body>我們仍需共生命的慷慨與繁華相愛,即使歲月以刻薄和荒蕪相欺。
</body>
</html>
  • biye.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="gbk">
    <title>畢業季</title>
</head>
<body>![](http://localhost:51017/day18/html/biyeji.png)
<br>當年以為六月不過也很平常
<br>當自己真正經歷了畢業
<br>才知道偶爾看到六月畢業季等字里所流露的種種想要重溫卻不敢提及的回憶
<br>畢業了
<br>那個夏天,我的畢業季,我的青春年少
<br>六月
<br>有人笑著說解脫,有人哭著說不捨
<br>那年,
<br>你對我說的你好
<br>在不知不覺中
<br>變成了
<br>再見。

</body>
</html>

biyeji.png

mytime.py文件

import time
def application(env,startResponse):
    status = 'HTTP/1.1 200 OK'
    responseHeaders = [('Server','bfe/1.0.8.18'),('Date','%s'%time.ctime()),('Content-Type','text/plain')]
    startResponse(status,responseHeaders)

    responseBody = str(time.ctime())
    return responseBody

訪問結果:


首頁
biye.html
mytime.py
'''
自定義的符合wsgi的框架
'''
import time


class Application(object):
    def __init__(self, urls):
        '''框架初始化的時候需要獲取路由列表'''
        self.urls = urls

    def __call__(self, env, startResponse):
        '''
        判斷是靜態資源還是動態資源。
        設置狀態碼和響應頭和響應體
        :param env:
        :param startResponse:
        :return:
        '''
        # 從請求頭中獲取文件名
        fileName = env.get('PATH_INFO')

        # 判斷靜態還是動態
        if fileName.startwith('/static'):
            fileName = fileName[7:]
            if '/' == fileName:
                filePath += '/index.html'
            else:
                filePath += fileName
            try:
                file = None
                file = open(filePath, 'r', encoding='gbk')
                responseBody = file.read()
                status = 'HTTP/1.1 200 OK'
                responseHeaders = [('Server', 'ererbai')]

            except FileNotFoundError:
                status = 'HTTP/1.1 404 Not Found'
                responseHeaders = [('Server', 'ererbai')]
                responseBody = '<h1>找不到<h1>'
            finally:
                startResponse(status, responseHeaders)
                if (file != None) and (not file.closed):
                    file.close()
        else:
            isHas = False  # 表示請求的名字是否在urls中,True:存在,False:不存在
            for url, func in self.urls:
                if url == fileName:
                    responseBody = func(env, startResponse)
                    isHas = True
                    break
            if isHas == False:
                status = 'HTTP/1.1 404 Not Found'
                responseHeaders = [('Server', 'ererbai')]
                responseBody = '<h1>找不到<h1>'
                startResponse(status, responseHeaders)
        return responseBody


def mytime(env, startResponse):
    status = 'HTTP/1.1 200 OK'
    responseHeaders = [('Server', 'time')]
    startResponse(status, responseHeaders)
    responseBody = str(time.ctime())
    return responseBody




def mynews(env, startResponse):
    status = 'HTTP/1.1 200 OK'
    responseHeaders = [('Server', 'news')]
    startResponse(status, responseHeaders)
    responseBody = str('xx新聞')
    return responseBody


'''路由列表'''
urls = [
    ('/mytime', mytime),
    ('/mynews', mynews)
]

application = Application(urls)

學習過程中遇到什麼問題或者想獲取學習資源的話,歡迎加入學習交流群
626062078,我們一起學Python!


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • using System.Xml; using System.Data; namespace DotNet.Utilities { /// <summary> /// Xml的操作公共類 /// </summary> public class XmlHelper { #region 欄位定義 /// ...
  • https加密鏈接,在訪問的過程中,可以保護你的隱私,保證你的敏感數據不會被別人偷窺,竊取。如果你的伺服器在境外,使用https,可以有更穩定的訪問體驗。接下來我們看一下ZKEACMS如何配置使用HTTPS。 ...
  • using System; using System.Security.Cryptography; using System.Text; namespace DotNet.Utilities { /// <summary> /// Encrypt 的摘要說明。 /// </summary> publ ...
  • 一、使用線程的理由 1、可以使用線程將代碼同其他代碼隔離,提高應用程式的可靠性。 2、可以使用線程來簡化編碼。 3、可以使用線程來實現併發執行。 二、基本知識 1、進程與線程:進程作為操作系統執行程式的基本單位,擁有應用程式的資源,進程包含線程,進程的資源被線程共用,線程不擁有資源。 2、前臺線程和 ...
  • using System; using System.Collections.Generic; using System.Text; using System.Diagnostics; namespace Utils { /// <summary> /// <para> </para> /// 常用 ...
  • WPF簡介 Windows Presentation Foundation(WPF)是微軟新一代圖形系統,運行在.NET Framework 3.0架構下,為用戶界面、2D/3D 圖形、文檔和媒體提供了統一的描述和操作方法。基於DirectX 9/10技術的WPF不僅帶來了前所未有的3D界面,而且其 ...
  • 在.Net框架中,如果您查看所有類型的的基類:System.Object類,將找到如下4個與相等判斷的方法: static Equals() virtual Equals() static ReferenceEquals() virtual GetHashCode() 除此之外,Microsoft已 ...
  • 對於堆排序會涉及一些完全二叉樹知識。對於待排序列{10, 2, 11, 8, 7},把它看成是一顆完全二叉樹,如下圖所示。 堆分為大根堆和小根堆:大根堆表示每個根節點均大於其子節點(L(i) >= L(2i) && L(i) >= L(2i + 1)),小根堆表示每個根節點均小於其子節點(L(i)  ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...