2010年10月17日 星期日

pynguin -- python下的海龜繪圖

簡介


海龜繪圖(logo)是一種學習程式語言概念很好的入門,網路上可以找到許多種語言實作的logo。這裡我介紹一個網路上找到的,以python+ Qt4建構的logo環境。除了可以學習基礎的程式概念,還能順便學python。


海龜繪圖

海龜繪圖(logo)

假想一隻帶著畫筆的海龜可以接受簡單的命令,例如向前走100步,或者左轉30度。通過對這隻海龜發送命令,可以讓它繪製出較為複雜的圖形,例如正方形,三角形,圓等。

海龜的移動相對於它本身所在的位置。例如,命令"左 90"意味著讓海龜左轉90度,學生可以站在海龜的角度來思考它將如何執行命令,這使得程序設計更加形象化,也更易於理解。

pynguin

於python下已有自帶的Tk版本海龜繪圖環境--turtle — Turtle graphics for Tk
這個作者製做了另一個基於python + Qt4 gui的海龜環境(雖然說預設顯示是隻企鵝)--pynguin。以下是企鵝的表現截圖:Screenshots

但由於需要安裝python與Qt4才能執行,對一般使用者來說有些麻煩。於是我將它包裝成獨立執行檔。可在此下載
解壓縮後執行pynguin.exe即可打開介面。



開啟範例

初 學者可先從作者提供的範例開始玩。從File -> Example -> ... 可以看到內附的例子。這裡選擇第2個例子。載入後,函式的程式碼會顯示在右上的黑色框框內。按右下的"Test"按鈕,右下的互動式介面會顯示將 要被執行的命令。在右下黑框內按下enter即可開始執行。Ctrl-C可中止執行。


命令簡述

可對企鵝下的命令如下:

# 相對坐標
forward(n)       # 前進n個像素距離。等同於fd(n)。
backward(n)      # 後退n個像素距離。等同於bk(n)。
left(n)          # 左轉角度n。等同於lt(n)。
right(n)         # 右轉角度n。等同於rt(n)。

circle(n)        # 畫圓, 半徑n個像素距離
circle(n, True)  # 以目前位置為圓心畫圓, 半徑n個像素距離
# 絕對坐標
goto(x,y)        # 移動至(點x, 點y)

reset()          # 清除繪圖區

更多說明在 doc\worksheets\

在右下黑框內輸入
fd(100)
lt(90)
fd(100)
lt(90)
即可看到企鵝隨著指令移動。


參考

python語法介紹--Python Handbook

更深入的海龜繪圖應用--碎形幾何參考網站:碎形幾何內涵與 Logo 程式繪圖

2010年10月5日 星期二

在視窗中嵌入shell介面

shell介面可以以文字形式,以直接鍵入函數與參數的方式控制應用程式,甚至執行一段script。

wxPython提供一個shell的應用程式,稱做PyShell,可以在
Python26\Lib\site-packages\wx-2.8-msw-unicode\wx\py目錄下
執行PyShell.py。

目錄下的shell.py中的Shell類別是此shell程式的核心,放到應用程式中即是一個現成的shell介面。此shell介面還支援自動完成與函數提示。


以下是簡單的嵌入範例,將Shell類別置入一個wx.Panel中。
"""
ShellPanel provides a shell interface in a panel.

# put shell in a frame
self.myShellPanel = ShellPanel(objDict = {'win':self}, parent = self)
"""

import wx
import wx.py as  py

class ShellPanel(wx.Panel):
    def __init__(self, objDict, *args, **kwds):
        """\
ShellPanel(objectDict, parent, ...)
    Create a Shell panel and put some object into this shell;
    Assign "myHelpInfo" object for default help text."""
        # format of objdict: { Name:object }

        kwds["style"] = wx.TAB_TRAVERSAL
        wx.Panel.__init__(self, *args, **kwds)

        self.objectDict = objDict
        self.myShell = py.shell.Shell(self, -1, locals = self.objectDict )

        sizer_Shell = wx.BoxSizer(wx.HORIZONTAL)
        sizer_Shell.Add(self.myShell, 1, wx.EXPAND, 0)
        self.SetSizer(sizer_Shell)

self.myShell = py.shell.Shell(self, -1, locals = objDict)
參數locals接收一個{名稱字串:物件}的字典,可將物件以對應的名稱字串在shell介面中操作。如果將應用程式(視窗)本身傳入,即可在shell介面中控制視窗,如上例將視窗物件以"win"命名,並在shell介面下輸入"win.SetTitle('Hello World')",便可改變視窗Title顯示。

此shell介面比起python內建的IDLE仍有些缺點。如下程式碼:
from time import sleep
for i in range(10): sleep(1)
無法如同在IDLE中,以鍵盤方式中斷。
(參考網頁:命令行的 Python shell 保留了處理鍵盤中斷( Ctrl +C)的能力...)

更多的Shell類別建構參數使用,請參考shell.py原始碼。

2010年10月3日 星期日

在py2exe包裝後的執行環境下執行python檔案

py2exe可以將python檔案包裝成獨立執行檔,便可在不安裝python interprter的環境下獨立執行。
然而每次執行py2exe包裝總得花上許多時間,如果能將時常變動的程式包裝成獨立的python檔案,並且在每次修改後都能直接加入包裝內,便可減少頻繁修改後的再次包裝,甚至此經常修改的部分可以讓使用者自行修改,以滿足實際需求。

py2exe包裝後,將python檔案放入library.zip內,可以在此找到原先的模組結構。雖然它將python文字檔編譯成pyc檔,但仍然可以將原先的文字檔放入並刪除pyc檔,這時候便會執行放入的文字檔。
 但在library.zip的文字檔無法直接打開修改。此外,跟著原先的模組取代,對使用者而言似乎不是這麼直覺,如果能在一個單純的資料夾下的固定檔案放置檔案,應該可以更容易使用。

如果將文字檔直接擺在library.zip之外的地方,會遇到無法找到模組的錯誤。這是因為py2exe包裝之後,sys.path內僅看得到"library.zip"。加入模組路徑之後即可解決。以下是簡單的程式碼示意,將根目錄加入sys.path。

        import sys
        # dist mode
        if len(sys.path)==1:
            path = sys.path[0]
            distDir = "library.zip"
            index = -1*len(distDir)
            if path[index:] == distDir:
                rootPath = path[:index]
                sys.path.append(rootPath)