web伺服器進階

  • 2019 年 10 月 6 日
  • 筆記

通過上面的學習,我們發現我們的web伺服器沒有徹底解耦

1、實現自己指定埠運行我們的web伺服器

如果我們的web伺服器埠被佔用,那麼我們的web伺服器直接掛掉。

怎麼實現?我們可以在執行的時候指定一個埠。

複習:

創建一個Demo.py

寫上:

import sys

print(sys.argv)

我們在黑窗口運行一個python文件的時候,執行命令:

python Demo 123 456

會輸出:['Demo.py', '123', '456']

可見,我們是可以給一個程式傳遞參數的。我們用這個功能,來給我們的web伺服器指定埠和框架。

2、利用1中的例子,再給一個框架名,讓他直接傳一個框架進入。

我們希望運行 python web伺服器 7891 Demo:application

來實現調用Demo框架的application方法。

3、寫一個配置文件,將web伺服器中的尋找文件的路徑寫進去。

解決上面三個問題才是真的解耦。

思路已經提供給大家,並且看基礎是能夠寫出來的。

接下來我們利用裝飾器完成路由功能。對裝飾器不懂的可以看看這篇文章:python基礎三

什麼是路由功能?

就是請求的url,我們上次通過if判斷來寫的,很噁心,用另一種方法些

我們將Demo框架寫成這樣(不用再修改web伺服器了):

URL_FUNC_DICT = dict()

def url_func(url):

def set_fun(func):

URL_FUNC_DICT[url] = func

def call_func(*args,**kwargs):

return func(*args,**kwargs)

return call_func

return set_fun

@url_func('/login.py')

def login():

# 這裡也可以讀取文件

return '<h1>登錄的頁面</h1>'

@url_func('/create.py')

def create():

return '<h1>註冊的頁面</h1>'

def application(evairon,start_response):

# 第一個參數返回狀態碼,第二個以鍵值的方式返回你想添加的head部分

start_response('200 ok',[('Content-Type','text/html;charset=utf-8')])

# 返回給網頁的內容

try:

file_name = evairon['path_info']

fun = URL_FUNC_DICT[file_name]

return fun()

except Exception as e:

return '未找到文件'

偽靜態實現

在前面說過我們只是暫時任務請求以.py結尾的url為動態的。實際上不是這樣。

上面才是動態網頁?

靜態的:域名/index.html

動態的:域名/index.aspx?page=xxx&xxxxx=xxxx,

偽靜態:域名/cour/index.html

web伺服器實現偽靜態:

修改web伺服器中判斷是.py結尾為以.html結尾,其它不用管。

修改Demo框架中裝飾器的參數為.html結尾。

給Demo框架連接資料庫並顯示到頁面

資料庫運用我們mysql教程中給大家演示的那個student資料庫。

對於python操作資料庫沒了解的請去看mysql資料庫系列文章。

mysql簡單基礎,我們在Demo新創建一個mysqldata方法,並且加上裝飾器

@url_func('/mysqldata.html')

def mysqldata():

conn = connect(host='localhost',port=3306,user='root',password='123456',database='student',charset='utf8')

cursor = conn.cursor()

cursor.execute("select * from studentinfo")

text = cursor.fetchall()

cursor.close()

conn.close()

return str(text)

在瀏覽器中輸入127.0.0.1:埠號/mysqldata.html即可看到內容。

查出來是這樣的:((1, '張三', 1, '男', 23, '武漢', b'x00'), (2, '小花', 2, '女', 20, '長沙', b'x00'), (3, '李四', 3, '男', 21, '上海', b'x00'), (4, '小貓', 1, '女', 18, '北京', b'x00'), (6, '小狗', 3, '女', 25, '成都', b'x00'), (7, '趙六', 1, '男', 26, '天津', b'x00'))

看著很噁心,給個格式。修改mysqldata方法:

這裡會用到html的知識點,希望自己補充。修改成:

@url_func('/mysqldata.html')

def mysqldata():

conn = connect(host='localhost',port=3306,user='root',password='123456',database='student',charset='utf8')

cursor = conn.cursor()

cursor.execute("select * from studentinfo")

text = cursor.fetchall()

cursor.close()

conn.close()

html = "<table border='1' width = '400px' cellspacing='0' cellpadding='0'>"

tr_html = '''

<tr>

<td>%s</td>

<td>%s</td>

<td>%s</td>

<td>%s</td>

<td>%s</td>

<td>%s</td>

<td>%s</td>

</tr>

'''

for item in text:

html += tr_html %(item[0],item[1],item[2],item[3],item[4],item[5],item[6])

html +="</table>"

return str(html)

這樣就好看多了。當然你想顯示什麼就資料庫查什麼就好了。

完善Demo框架

1、給路由添加正則

現在我們的url返回的都是固定的,比如我們想要刪除一個數據,請求的url為/delete/xxx.html

我們需要傳遞一個xxx,表示id,這個id是不確定的,所以我們需要正則匹配,只要是這種格式,我們都執行

delete方法。修改如下:

修改application方法:

def application(evairon,start_response):

# 第一個參數返回狀態碼,第二個以鍵值的方式返回你想添加的head部分

start_response('200 ok',[('Content-Type','text/html;charset=utf-8')])

# 返回給網頁的內容

try:

file_name = evairon['path_info']

for url,func in URL_FUNC_DICT.items():

# 匹配是否有這個函數,有返回回去

ret = re.match(url,file_name)

if ret:

return func(ret)

except Exception as e:

return '未找到文件 %s'%e

添加delete方法,並匹配所有url為/delete/xxx.html格式的都執行該方法。

@url_func(r'/delete/(d+).html')

def delete(ret):

return '刪除方法。ok'

由於給所有函數傳遞了一個url,所以需要給上面的函數都添加一個參數。

執行:成功返回刪除方法。ok,那我們繼續完善刪除方法。

@url_func(r'/delete/(d+).html')

def delete(ret):

# 獲取id值

id = ret.group(1)

# 執行sql刪除

conn = connect(host='localhost',port=3306,user='root',password='123456',database='student',charset='utf8')

cursor = conn.cursor()

count = cursor.execute("delete from studentinfo where studentid = %s",(id,))

if count:

conn.commit()

cursor.close()

conn.close()

return '刪除成功。ok!!'

else:

return '刪除失敗!'

其他修改啊,添加,只是sql語句不同,都大同小異。

不過在修改的時候要修改正則,傳給數據的還要有修改值沒有了解post請求就換個正則匹配

比如127.0.0.1/修改方法/要修改的id/要修改的內容.html,用正則匹配出id和要修改的內容就可以了。

但是有個問題,當我們傳遞的內容或者漢子的時候會出現亂碼,因為是通過url傳遞的,中途會有個url編碼的過程,

我們需要解碼:

1、需要導入模組

import urllib

解碼:urllib.parse.unquote()

編碼:urllib.parse.quote()

添加日誌模組

不會日誌模組需要看基礎:python常用模組二

導入日誌模組:import logging

修改application方法:

def application(evairon,start_response):

# 第一個參數返回狀態碼,第二個以鍵值的方式返回你想添加的head部分

start_response('200 ok',[('Content-Type','text/html;charset=utf-8')])

file_name = evairon['path_info']

# 寫入日誌

logging.basicConfig(level=logging.INFO,

filename = './log.txt',

filemode = 'a',

format = '%(asctime)s – %(filename)s[line:%(lineno)d]-%(levelname)s:%(message)s'

)

logging.info('訪問了%s'%file_name)

# 返回給網頁的內容

try:

for url,func in URL_FUNC_DICT.items():

# 匹配是否有這個函數,有返回回去

ret = re.match(url,file_name)

if ret:

return func(ret)

except Exception as e:

logging.WARNING('找不到文件')

return '未找到文件 %s'%e