CMSimple Drupal Yii 內容管理系統三方案 - 提升台灣中小企業競爭力

目前位置:   首頁 > Welcome to CMSimple > CherryPy and Mako

CherryPy and Mako

CherryPy 是一套源自 2001 年, 且目前版本支援 Python3 的全球資訊網框架, 而 Mako 則是可與 CherryPy 結合使用的樣版引擎.

為何選擇 CherryPy:

1. 不僅記憶體需求低, 而且使用簡單.

全球資訊網上的 CherryPy Hello World, 如下:

import cherrypy
class HelloWorld(object):
    def index(self):
        return "Hello World!"
    index.exposed = True
cherrypy.quickstart(HelloWorld())

 假如要送到 OpenShift 雲端平台上執行, 則改為:

import cherrypy
class HelloWorld(object):
    def index(self):
        return "Hello World!"
    index.exposed = True
#cherrypy.quickstart(HelloWorld())
application = cherrypy.Application(HelloWorld())

2. 提供完整的全球資訊網工具與延伸架構, 功能強大.

無論是 SSL 或虛擬主機, 全部內建, 符合一般網際程式開發使用.

3. 模組化的設計, 歷經第一代求有, 第二代求好, 但目前進入第三代求精美的階段.

使用 Mako 樣版引擎:

from mako.template import Template
from mako.lookup import TemplateLookup

 參考資料:

http://tools.cherrypy.org/wiki/Mako


CherryPy 上的 Brython console:

直接在瀏覽器中執行 Python3.

import cherrypy
import os
class Brython(object):
    def index(self):
        return '''
<script src="/brython/brython.js"></script>
<script>
window.onload = function(){
    brython(1);
}
</script><script type="text/python">
import sys
import time
import dis
if sys.has_local_storage:
    from local_storage import storage
else:
    storage = False
def reset_src():
    if storage:
        doc['src'].value = storage["py_src"]
def write(data):
    doc["console2"].value += str(data)
#sys.stdout = object()    #not needed when importing sys via src/Lib/sys.py
sys.stdout.write = write
def to_str(xx):
    return str(xx)
doc['version'].text = '.'.join(map(to_str,sys.version_info))
# 配合 20130817 版本, 改為下列流程
def write(data):
    doc["console2"].value += str(data)
sys.stdout.write = write
sys.stderr.write = write
# 結束 20130817 版本修改
output = ''
def show_console2():
    doc["console2"].value = output
    doc["console2"].cols = 60
def clear_text():
    log("event clear")
    doc['console2'].value=''
    #doc['src'].value=''
def clear_canvas():
    canvas = doc["plotarea"]
    ctx = canvas.getContext("2d")
    ctx.clearRect(0, 0, canvas.width, canvas.height)
def run():
    global output
    doc["console2"].value=''
    doc["console2"].cols = 60
    src = doc["src"].value
    if storage:
        storage["py_src"]=src
    t0 = time.time()
    exec(src)
    output = doc["console2"].value
    print('<done in %s ms>' %(time.time()-t0))
def show_js():
    src = doc["src"].value
    doc["console2"].cols = 90
    doc["console2"].value = dis.dis(src)
</script>
<table width=80%>
<tr><td style="text-align:center"><b>Python</b>
</td>
<td>&nbsp;</td>
<th><input type="button" value="Console" onClick="show_console2()"></th>
<th><input type="button" value="Javascript" onClick="show_js()"></th>
</tr>
<tr><td><div id="editor"></div><textarea id="src" name=form_34ed066df378efacc9b924ec161e7639program cols="60" rows="20">import math
半徑 = 22.5
圓面積 = (math.pi*(半徑**2))/4
print(math.pi*(半徑**2))
正方形面積 = 半徑*半徑
圓缺角 = 正方形面積 - 圓面積
print(圓缺角)
長度 = 10
三角形缺角 = 長度*長度/2
print(三角形缺角)
大四方形邊長 = 60
內面積 = 大四方形邊長**2 - 三角形缺角 - 圓缺角
print(內面積)</textarea></td><td><input type="button" value="Run" onClick="run()"></td>
<td><input type="button" value="Clear Output" onClick="clear_text()">
<input type="button" value="Clear Canvas" onClick="clear_canvas()">
</td>
<td colspan=2><textarea id="console2" cols="60" rows="20"></textarea></td>
</tr>
<tr><td colspan=2>
<p>Brython version <span id="version"></td>
</tr>
<tr><td colspan="4">
<div id="outputdiv"></div>
<textarea id="dataarea" cols=30 rows=5></textarea>
</td>
</tr>
<tr><td colspan="4">
<canvas id="plotarea" width="640" height="640"></canvas>
</td>
</tr>
</table>
'''
    index.exposed = True
# 確定程式檔案所在目錄
_curdir = os.path.join(os.getcwd(), os.path.dirname(__file__))
# 配合程式檔案所在目錄設定靜態目錄或靜態檔案
application_conf = {'/brython':{
        'tools.staticdir.on': True,
        'tools.staticdir.dir': _curdir+"/brython"}
    }
cherrypy.quickstart(Brython(), config = application_conf)

可在 Brython Console 執行繪圖的程式 :

#coding: utf-8
from math import *
import time
import random
# 準備繪圖畫布
canvas = doc["plotarea"]
ctx = canvas.getContext("2d")
# 定義座標轉換(0, 0) 到 (75, 20)
def change_ref_system(x, y):
    return (20 + x * 8, 420 - y * 20)
# 定義畫線函式
def draw_line(x1, y1, x2, y2, linethick = 3, color = "black"):
    ctx.beginPath()
    ctx.lineWidth = linethick
    ctx.moveTo(x1, y1)
    ctx.lineTo(x2, y2)
    ctx.strokeStyle = color
    ctx.stroke()
# 定義一個點類別
class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y
    def distanceTo(self, obj):
        if isinstance(obj, Point):
            return sqrt(pow(obj.x - self.x, 2) + pow(obj.y- self.y, 2))
        else:
            raise TypeError("Invalid type in Point.distanceTo()")
# 定義一個線類別
class Line:
    def __init__(self, p1, p2):
        self.p1 = p1
        self.p2 = p2
        # 定義一個 Line 的屬性 length
        self.length = self.p1.distanceTo(self.p2)
        self.deg = pi/180
    def rotate(self, angle):
        # 以 p1  為旋轉中心點
        # angle 為右手則旋轉角度
        # 這裡以左上角為原點, x 向右為正, y 向下為正
        self.p2.x = self.p1.x + self.length*cos(angle*self.deg)
        self.p2.y = self.p1.y - self.length*sin(angle*self.deg)
# 定義一個回呼繪圖函式
dataset = []
def graph():
    p1 = Point(0, 0)
    p2 = Point(10, 0)
    data = random.random() * 20
    doc["dataarea"] <= '%s, ' % str(data)[0:5]
    dataset.append(data)
    if len(dataset) == 1:
        x, y = change_ref_system(len(dataset), data)
        draw_line(x, y, x, y, linethick=3, color="blue")
    else:
        x1, y1 = change_ref_system(len(dataset)-1, dataset[-2])
        x2, y2 = change_ref_system(len(dataset), data)
        draw_line(x1, y1, x2, y2, linethick=3, color="blue")
    if len(dataset) >= 100:
        print(len(dataset))
        time.clear_interval(work)
p1 = Point(0, 0)
p2 = Point(10, 0)
p3 = Point(6.5, 7.8)
print("點 p1 到點 p2 的距離:", p1.distanceTo(p2))
line1 = Line(p1, p2)
print("線 line1 的長度:", line1.length)
# 以 p3 為圓心, 旋轉 90 度
line1.rotate(90)
#work = time.set_interval(graph, 100)
print("旋轉後, line1 的長度:", line1.length)
print("旋轉後, p1 的座標:", line1.p1.x, ",", line1.p1.y)
print("旋轉後, p2 的座標:", line1.p2.x, ",",  line1.p2.y)
x1, y1 = change_ref_system(0, 0)
for 索引 in range(0, 70, 4):
    x2, y2 = change_ref_system(索引, 20)
    draw_line(x1, y1, x2, y2, linethick=3, color="blue")
x1, y1 = change_ref_system(70, 0)
for 索引 in range(0, 70, 4):
    x2, y2 = change_ref_system(索引, 20)
    draw_line(x1, y1, x2, y2, linethick=3, color="red")

 

參考檔案: CherryPy_Brython_ex1.7z

CherryPy 透過 Brython 執行 html5 平面繪圖:

'''
1. 利用 CherryPy 網際框架啟動全球資訊網伺服器, 具備 session, 
自定錯誤訊息, https 啟動等功能.
2. 利用 brython.js 讓使用者可以在網頁上以 Python3 語法控制 html5 canvas 物件.
3. 使用者必須熟悉 Python3, Javascript 運作模式, 以及 html5 與 http 等基本架構.
'''
import cherrypy
import 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
    }
    # var1 與 var2 設為輸入變數, 且給定內建值
    def index(self, var1=200, var2=200):
        output = '''
<html>
<script src="/test.js">
</script>
<!-- 必須導入 brython.js 程式 -->
<script src="jscript/brython.js"></script>
<script>
// 所有的 brython 程式都必許執行 brython() 函式
// 而且是在瀏覽器視窗載入時就先執行 brython()
window.onload = function(){
    brython();
}
</script>
<!-- 以下則是利用 Python3 語法編寫的網頁程式 -->
<script type="text/python">
# 準備在 id="page" 的 canvas 中繪圖
canvas = doc["page"]
ctx = canvas.getContext("2d")
ctx.moveTo(100,100)
'''+'''
ctx.lineTo('''+str(var1)+''','''+str(var2)+''')
ctx.stroke()
</script>
<!-- 這裡就是實際繪出畫布內容的位置 -->
<canvas width="550" height="550" id="page">
<i>your browser does not support HTML5 canvas, or Javascript is turned off</i>
</canvas>
</html>
        '''
        return output
    index.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})
# 確定程式檔案所在目錄
_curdir = os.path.join(os.getcwd(), os.path.dirname(__file__))
# 配合程式檔案所在目錄設定靜態目錄或靜態檔案
application_conf = {'/jscript':{
        'tools.staticdir.on': True,
        'tools.staticdir.dir': "/jscript"}, 
    '/test.js': {
        'tools.staticfile.on': True,
        'tools.staticfile.filename': os.path.join(_curdir, 'test.js'),
        }
    }
# 只將 Server 在 https 模式下啟動 - 第一種方式
'''
cherrypy.config.update({'server.socket_port': 8093, 'server.socket_host': '127.0.0.1',
                        'server.ssl_certificate': 'v:/certificates/ssl_cert.pem',
                        'server.ssl_private_key': 'v:/certificates/ssl_cert.pem'})
'''
# 將 Server 以 https 模式啟動 - 第二種方式
# 在 OpenShift 內建 self signed ssl, 因此蓋掉下列 SSL 設定
'''
cherrypy.server.socket_port = 8093
cherrypy.server.socket_host = '127.0.0.1'
cherrypy.server.ssl_certificate = 'v:/certificates/ssl_cert.pem'
cherrypy.server.ssl_private_key = 'v:/certificates/ssl_cert.pem'
'''
'''
配合 https 啟動, 蓋掉有關 http 啟動的設定
os.system("V:/Chrome/chrome.exe http://localhost:8083")
cherrypy.server.socket_port = 8083
cherrypy.server.socket_host = '127.0.0.1'
'''
# 單機執行時採下一行, 在 OpenShift 則使用下下一行
#cherrypy.quickstart(HelloWorld(), config = application_conf)
application = cherrypy.Application(HelloWorld(), config = application_conf)

 

Powered by CMSimple_XH| Template: ge-webdesign.de| 登入