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
%s - %s (%d)
""" ############################################################### # 唯一的 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, 請輸入留言. 更改作者代號.
""" % (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