Cherrypy 相關功能介紹
CherryPy 模組安裝:
pip install cherrypy
CherryPy 程式架構
最簡單的 CherryPy 程式:
#coding: utf-8 # 最簡單的 CherryPy 程式 # 導入 cherrypy 與 os 模組 import cherrypy,os # 建立 HelloWorld 類別物件 class HelloWorld(object): # 定義一個會內建呼叫的 index 方法 def index(self): # 傳回字串 return "Hello World!" # 可以從外部以 index 連結呼叫此方法 index.exposed = True # 利用 os.system() 執行 chrome.exe, 直接以瀏覽器開啟 cherrypy 伺服器 os.system("V:/Chrome/chrome.exe http://localhost:8083") # 設定 cherrypy 的連結埠號為 8083 cherrypy.server.socket_port = 8083 # 設定 cherrypy 的啟動 IP 為 127.0.0.1 cherrypy.server.socket_host = '127.0.0.1' # 以 HelloWorld() 物件啟動 cherrypy cherrypy.quickstart(HelloWorld())
從上面的程式執行, 可以了解 CherryPy 的基本架構, 主要利用 HelloWorld() 物件中的方法來進行呼叫執行, 而且一旦啟動, 會自動呼叫 index() 方法, 而使用者也可以自行建立其他方法.
import cherrypy,os class HelloWorld(object): def index(self): return "Hello World!" index.exposed = True def mymethod(self): return "This is my method!" mymethod.exposed = True os.system("V:/Chrome/chrome.exe http://localhost:8083/mymethod") cherrypy.server.socket_port = 8083 cherrypy.server.socket_host = '127.0.0.1' cherrypy.quickstart(HelloWorld())
下一個範例, 特別將 mymethod.exposed = True 蓋去, 表示使用者無法直接利用瀏覽器呼叫, 而只能以 self.mymethod() 的方式, 由其他可以直接呼叫的方法中執行, 下列程式執行後, http://localhost:8083 與 http://localhost:8083/index 結果相同, 但是卻無法直接呼叫 mymethod().
import cherrypy,os class HelloWorld(object): def index(self): #return "Hello World!" return self.mymethod() index.exposed = True def mymethod(self): return "This is my method!" #mymethod.exposed = True os.system("V:/Chrome/chrome.exe http://localhost:8083") os.system("V:/Chrome/chrome.exe http://localhost:8083/index") os.system("V:/Chrome/chrome.exe http://localhost:8083/mymethod") cherrypy.server.socket_port = 8083 cherrypy.server.socket_host = '127.0.0.1' cherrypy.quickstart(HelloWorld())
Python3 程式與 Javascript 程式交換變數, 使用者呼叫時, 由 URL 連結中輸入變數值, 然後交由 Python3 傳給 Javascript 程式.
import cherrypy,os class HelloWorld(object): def index(self,var1=None): outString = ''' ''' return outString index.exposed = True os.system("V:/Chrome/chrome.exe http://localhost:8083?var1=123") os.system("V:/Chrome/chrome.exe http://localhost:8083?var1=Hello") cherrypy.server.socket_port = 8083 cherrypy.server.socket_host = '127.0.0.1' cherrypy.quickstart(HelloWorld())
利用 cherrypy.request.method 來判定變數取值的方法, 這裡透過 GET 取得變數值, 另外以表單取變數值的方法稱為 POST.
import cherrypy,os class HelloWorld(object): def index(self,var1=None): outString = ''' ''' outString += cherrypy.request.method return outString index.exposed = True os.system("V:/Chrome/chrome.exe http://localhost:8083?var1=123") cherrypy.server.socket_port = 8083 cherrypy.server.socket_host = '127.0.0.1' cherrypy.quickstart(HelloWorld())
CherryPy 與 session
import cherrypy,os class HelloWorld(object): # cherrypy 執行的設定檔案, 以 dictionay 資料格式設定 _cp_config = { # 配合 utf-8 格式之表單內容 # 若沒有 utf-8 encoding 設定,則表單不可輸入中文 'tools.encode.encoding': 'utf-8', 'tools.sessions.on' : True, 'tools.sessions.storage_type' : 'file', 'tools.sessions.locking' : 'explicit', 'tools.sessions.storage_path' : 'v:/tmp', 'tools.sessions.timeout' : 60 } def index(self,var1=None): outString = ''' ''' outString += cherrypy.request.method count = cherrypy.session.get('count', 0) + 1 cherrypy.session['count'] = count outString += " count is now:"+str(count) return outString index.exposed = True def reset_session(self): # delete all session data #cherrypy.session.delete() # only delete 'count' session del cherrypy.session['count'] return "count is deleted" reset_session.exposed = True os.system("V:/Chrome/chrome.exe http://localhost:8083?var1=123") cherrypy.server.socket_port = 8083 cherrypy.server.socket_host = '127.0.0.1' cherrypy.quickstart(HelloWorld())
再加上客製化錯誤訊息:
#coding: utf-8 import cherrypy,os class HelloWorld(object): # cherrypy 執行的設定檔案, 以 dictionay 資料格式設定 _cp_config = { # 配合 utf-8 格式之表單內容 # 若沒有 utf-8 encoding 設定,則表單不可輸入中文 'tools.encode.encoding': 'utf-8', 'tools.sessions.on' : True, 'tools.sessions.storage_type' : 'file', 'tools.sessions.locking' : 'explicit', 'tools.sessions.storage_path' : 'v:/tmp', 'tools.sessions.timeout' : 60 } def index(self,**var): outString = ''' ''' except: outString += ''' ''' pass outString += cherrypy.request.method count = cherrypy.session.get('count', 0) + 1 cherrypy.session['count'] = count outString += " count is now:"+str(count) return outString index.exposed = True def reset_session(self): # delete all session data #cherrypy.session.delete() # only delete 'count' session del cherrypy.session['count'] return "count is deleted" reset_session.exposed = True # 客製化的 error 402 函式 def error_page_402(status, message, traceback, version): return "Error %s - 抱歉! 發生 402 錯誤!" % status cherrypy.config.update({'error_page.402': error_page_402}) def error_page_404(status, message, traceback, version): return "Error %s - 抱歉! 發生 404 錯誤!" % status cherrypy.config.update({'error_page.404': error_page_404}) os.system("V:/Chrome/chrome.exe http://localhost:8083?var1=123") cherrypy.server.socket_port = 8083 cherrypy.server.socket_host = '127.0.0.1' cherrypy.quickstart(HelloWorld())
CherryPy 以 https 啟動
CherryPy 程式以 http 及 https 模式啟動
#coding: utf-8 import cherrypy,os class HelloWorld(object): # cherrypy 執行的設定檔案, 以 dictionay 資料格式設定 _cp_config = { # 配合 utf-8 格式之表單內容 # 若沒有 utf-8 encoding 設定,則表單不可輸入中文 'tools.encode.encoding': 'utf-8', 'tools.sessions.on' : True, 'tools.sessions.storage_type' : 'file', 'tools.sessions.locking' : 'explicit', 'tools.sessions.storage_path' : 'v:/tmp', 'tools.sessions.timeout' : 60 } def index(self,**var): outString = ''' ''' except: outString += ''' ''' pass outString += cherrypy.request.method count = cherrypy.session.get('count', 0) + 1 cherrypy.session['count'] = count outString += " count is now:"+str(count) return outString index.exposed = True def reset_session(self): # delete all session data #cherrypy.session.delete() # only delete 'count' session del cherrypy.session['count'] return "count is deleted" reset_session.exposed = True # 客製化的 error 402 函式 def error_page_402(status, message, traceback, version): return "Error %s - 抱歉! 發生 402 錯誤!" % status cherrypy.config.update({'error_page.402': error_page_402}) def error_page_404(status, message, traceback, version): return "Error %s - 抱歉! 發生 404 錯誤!" % status cherrypy.config.update({'error_page.404': error_page_404}) os.system("V:/Chrome/chrome.exe http://localhost:8083?var1=123") os.system("V:/Chrome/chrome.exe https://localhost:8093?var1=123") cherrypy.config.update({'server.socket_port': 8083, 'server.socket_host': '127.0.0.1'}) from cherrypy._cpserver import Server server = Server() server.socket_port = 8093 server.socket_host = '127.0.0.1' server.ssl_certificate = 'v:/ssl_cert.pem' server.ssl_private_key = 'v:/ssl_cert.pem' server.subscribe() #cherrypy.server.socket_port = 8083 #cherrypy.server.socket_host = '127.0.0.1' cherrypy.quickstart(HelloWorld())
僅使用 https 模式啟動上述 CherryPy 程式:
#coding: utf-8 import cherrypy,os class HelloWorld(object): # cherrypy 執行的設定檔案, 以 dictionay 資料格式設定 _cp_config = { # 配合 utf-8 格式之表單內容 # 若沒有 utf-8 encoding 設定,則表單不可輸入中文 'tools.encode.encoding': 'utf-8', 'tools.sessions.on' : True, 'tools.sessions.storage_type' : 'file', 'tools.sessions.locking' : 'explicit', 'tools.sessions.storage_path' : 'v:/tmp', 'tools.sessions.timeout' : 60 } def index(self,**var): outString = ''' ''' except: outString += ''' ''' pass outString += cherrypy.request.method count = cherrypy.session.get('count', 0) + 1 cherrypy.session['count'] = count outString += " count is now:"+str(count) return outString index.exposed = True def reset_session(self): # delete all session data #cherrypy.session.delete() # only delete 'count' session del cherrypy.session['count'] return "count is deleted" reset_session.exposed = True # 客製化的 error 402 函式 def error_page_402(status, message, traceback, version): return "Error %s - 抱歉! 發生 402 錯誤!" % status cherrypy.config.update({'error_page.402': error_page_402}) def error_page_404(status, message, traceback, version): return "Error %s - 抱歉! 發生 404 錯誤!" % status cherrypy.config.update({'error_page.404': error_page_404}) os.system("V:/Chrome/chrome.exe https://localhost:8093?var1=123") cherrypy.config.update({'server.socket_port': 8093, 'server.socket_host': '127.0.0.1', 'server.ssl_certificate': 'v:/ssl_cert.pem', 'server.ssl_private_key': 'v:/ssl_cert.pem'}) #cherrypy.server.socket_port = 8083 #cherrypy.server.socket_host = '127.0.0.1' cherrypy.quickstart(HelloWorld())
也可以採用下列方式, 將 CherryPy 程式以 https 模式啟動:
#coding: utf-8 import cherrypy,os class HelloWorld(object): # cherrypy 執行的設定檔案, 以 dictionay 資料格式設定 _cp_config = { # 配合 utf-8 格式之表單內容 # 若沒有 utf-8 encoding 設定,則表單不可輸入中文 'tools.encode.encoding': 'utf-8', 'tools.sessions.on' : True, 'tools.sessions.storage_type' : 'file', 'tools.sessions.locking' : 'explicit', 'tools.sessions.storage_path' : 'v:/tmp', 'tools.sessions.timeout' : 60 } def index(self,**var): outString = ''' ''' except: outString += ''' ''' pass outString += cherrypy.request.method count = cherrypy.session.get('count', 0) + 1 cherrypy.session['count'] = count outString += " count is now:"+str(count) return outString index.exposed = True def reset_session(self): # delete all session data #cherrypy.session.delete() # only delete 'count' session del cherrypy.session['count'] return "count is deleted" reset_session.exposed = True # 客製化的 error 402 函式 def error_page_402(status, message, traceback, version): return "Error %s - 抱歉! 發生 402 錯誤!" % status cherrypy.config.update({'error_page.402': error_page_402}) def error_page_404(status, message, traceback, version): return "Error %s - 抱歉! 發生 404 錯誤!" % status cherrypy.config.update({'error_page.404': error_page_404}) os.system("V:/Chrome/chrome.exe https://localhost:8093?var1=123") cherrypy.server.socket_port = 8093 cherrypy.server.socket_host = '127.0.0.1' cherrypy.server.ssl_certificate = 'v:/ssl_cert.pem' cherrypy.server.ssl_private_key = 'v:/ssl_cert.pem' cherrypy.quickstart(HelloWorld())
CherryPy 的虛擬主機 (Virtual Hosting) 設定方法:
#coding: utf-8 import cherrypy,os ''' CherryPy 的虛擬主機對應 1. 修改 Windows C:\WINDOWS\system32\drivers\etc\hosts 檔案 127.0.0.1 server1.my.domain 127.0.0.1 server2.my.domain 2. 以下設定將可透過 https://server1.my.domain:8093 https://server2.my.domain:8093 連結到同一 CherryPy 網際程式的不同對應物件方法 ''' class Root(object): def __init__(self): self.server1 = HelloWorld1() self.server2 = HelloWorld2() class HelloWorld1(object): # cherrypy 執行的設定檔案, 以 dictionay 資料格式設定 _cp_config = { # 配合 utf-8 格式之表單內容 # 若沒有 utf-8 encoding 設定,則表單不可輸入中文 'tools.encode.encoding': 'utf-8', 'tools.sessions.on' : True, 'tools.sessions.storage_type' : 'file', 'tools.sessions.locking' : 'explicit', 'tools.sessions.storage_path' : 'v:/tmp', 'tools.sessions.timeout' : 60 } def index(self,**var): outString = '''這是 server1.my.domain ''' except: outString += ''' ''' pass outString += cherrypy.request.method count = cherrypy.session.get('count', 0) + 1 cherrypy.session['count'] = count outString += " count is now:"+str(count) return outString index.exposed = True def reset_session(self): # delete all session data #cherrypy.session.delete() # only delete 'count' session del cherrypy.session['count'] return "count is deleted" reset_session.exposed = True # 客製化的 error 402 函式 def error_page_402(status, message, traceback, version): return "Error %s - 抱歉! 發生 402 錯誤!" % status cherrypy.config.update({'error_page.402': error_page_402}) def error_page_404(status, message, traceback, version): return "Error %s - 抱歉! 發生 404 錯誤!" % status cherrypy.config.update({'error_page.404': error_page_404}) class HelloWorld2(object): # cherrypy 執行的設定檔案, 以 dictionay 資料格式設定 _cp_config = { # 配合 utf-8 格式之表單內容 # 若沒有 utf-8 encoding 設定,則表單不可輸入中文 'tools.encode.encoding': 'utf-8', 'tools.sessions.on' : True, 'tools.sessions.storage_type' : 'file', 'tools.sessions.locking' : 'explicit', 'tools.sessions.storage_path' : 'v:/tmp', 'tools.sessions.timeout' : 60 } def index(self,**var): outString = '''這是 server2.my.domain ''' except: outString += ''' ''' pass outString += cherrypy.request.method count = cherrypy.session.get('count', 0) + 1 cherrypy.session['count'] = count outString += " count is now:"+str(count) return outString index.exposed = True def reset_session(self): # delete all session data #cherrypy.session.delete() # only delete 'count' session del cherrypy.session['count'] return "count is deleted" reset_session.exposed = True # 客製化的 error 402 函式 def error_page_402(status, message, traceback, version): return "Error %s - 抱歉! 發生 402 錯誤!" % status cherrypy.config.update({'error_page.402': error_page_402}) def error_page_404(status, message, traceback, version): return "Error %s - 抱歉! 發生 404 錯誤!" % status cherrypy.config.update({'error_page.404': error_page_404}) os.system("V:/Chrome/chrome.exe https://server1.my.domain:8093?var1=123") os.system("V:/Chrome/chrome.exe https://server2.my.domain:8093?var1=123") hostmap = { 'server1.my.domain:8093': '/server1', 'server2.my.domain:8093': '/server2', } config = { 'request.dispatch': cherrypy.dispatch.VirtualHost(**hostmap) } cherrypy.server.socket_port = 8093 cherrypy.server.socket_host = '127.0.0.1' cherrypy.server.ssl_certificate = 'v:/ssl_cert.pem' cherrypy.server.ssl_private_key = 'v:/ssl_cert.pem' #cherrypy.quickstart(HelloWorld()) cherrypy.quickstart(Root(), '/', {'/': config})
以下則為 CherryPy 網際留言簿程式範例:
#coding: utf-8 # # note.py CherryPy 應用範例程式 ''' 本程式在展示 CherryPy 程式的: 1. session 用法 2. 靜態內容引用方法 3. 全域設定與靜態內容設定方法 4. 自動處理數列頁面內容的用法 5. 表單列印與資料處理方法 6. 重新導向用法 以及 Python3 程式的: 1. 重新定義物件 __str__ 字串傳回方法 2. 留言時間資料的字串轉換處理 3. 數列資料的反向排序與附加 ''' # # 導入 Python 標準模組 import os, time # 導入 cherrypy 模組 import cherrypy # 確定程式檔案所在目錄 _curdir = os.path.join(os.getcwd(), os.path.dirname(__file__)) # _notes 為一全域數列變數, 主要利用記憶體儲存使用者的留言內容 _notes = [] # 相關超文件變數 _header = """留言簿 """ _footer = """""" _note_form = """""" _author_form = """""" _note_view = """
%s""" ############################################################### # 唯一的 domain object (也可稱為 Model) ############################################################### class Note(object): def __init__(self, author, note): self.id = None self.author = author self.note = note self.timestamp = time.gmtime(time.time()) # 改寫物件字串資料列出的傳回內容 def __str__(self): return self.note ############################################################### # Note 應用程式的主要進入點 ############################################################### class NoteApp: """ 打算用 CherryPy 啟動的程式物件 """ # 啟動 session 工具 # 採用 utf-8 編碼 _cp_config = {'tools.sessions.on': True, # 若無 utf-8 編碼指定, 無法處理中文 'tools.encode.encoding': 'utf-8' } def _render_note(self, note): """將 note 轉為頁面的 html 內容, 輸入為 3 個字串與兩個數字""" return _note_view % (note, note.author, # 依照格式列出留言時間 time.strftime("%a, %d %b %Y %H:%M:%S", note.timestamp), note.id, note.id) # 這是前置指令用法, 與 index.exposed = True 功能相同 @cherrypy.expose def index(self): # 取出存在 session 的作者名稱, 若無資料則將 author 設為 None author = cherrypy.session.get('author', None) # 頁面數列先放入超文件標頭 page = [_header] # 若有作者資料則附加在 page 數列, 否則要求輸入 if author: page.append("""%s - %s (%d)您好 %s, 請輸入留言. 更改作者代號.""" % (author,)) page.append(_note_form) else: page.append("""""") # 以反向排列將 notes 附加到 page notes = _notes[:] notes.reverse() for note in notes: page.append(self._render_note(note)) # 在頁面最後附上 _footer page.append(_footer) # CherryPy 會自動處理所傳回的 page 數列資料 return page @cherrypy.expose def note(self, id): # 根據代號取出留言 try: note = _notes[int(id)] except: # 若為無效 id, 則傳回找不到資料之訊息 raise cherrypy.NotFound return [_header, self._render_note(note), _footer] @cherrypy.expose def post(self, text): author = cherrypy.session.get('author', None) # 若 session 無作者資料, 則導向設定作者代號頁面 if not author: raise cherrypy.HTTPRedirect('/author') # Note 為 domain object Note 的一個案例 note = Note(author, text) _notes.append(note) note.id = _notes.index(note) raise cherrypy.HTTPRedirect('/') class Author(object): @cherrypy.expose def index(self): return [_header, _author_form, _footer] @cherrypy.expose def set(self, name): cherrypy.session['author'] = name return [_header, """ %s 歡迎蒞臨! 請留言 留言. """ % (name,), _footer] if __name__ == '__main__': # 全域設定 global_conf = { 'global': { 'autoreload.on': False, 'server.socket_host': '127.0.0.1', 'server.socket_port': 8083, 'server.protocol_version': 'HTTP/1.1' }} application_conf = { '/style.css': { 'tools.staticfile.on': True, 'tools.staticfile.filename': os.path.join(_curdir, 'style.css'), } } # 更新 CherryPy 的全域設定 cherrypy.config.update(global_conf) # 建立一個應用案例 note_app = NoteApp() # 附加一個作者類別案例到主應用案例中的 author 屬性 note_app.author = Author() # 以 chrome 開啟網頁 os.system("V:/Chrome/chrome.exe http://localhost:8083") # 以 application_conf 中的設定啟動 note_app cherrypy.quickstart(note_app, config = application_conf) # 以下為 style.css 檔案內容 ''' html, body { background-color: #DEDEDE; padding: 0px; marging: 0px; height: 100%; } .container { border-color: #A1A1A1; border-style: solid; border-width: 1px; background-color: #FFF; margin: 10px 150px 10px 150px; height: 100%; width: 400px; } a:link { text-decoration: none; color: #A1A1A1; } a:visited { text-decoration: none; color: #A1A1A1; } a:hover { text-decoration: underline; } input { border: 1px solid #A1A1A1; } .form { margin: 5px 5px 5px 5px; } .info { font-size: 70%; color: #A1A1A1; } '''
Comments
comments powered by Disqus