版權聲明

所有的部落格文章都可以在右邊[blog文章原始檔案]下載最原始的文字檔案,並依你高興使用 docutil 工具轉換成任何對應的格式方便離線閱覽,除了集結成書販賣歡迎任意取用,引用
顯示具有 python 標籤的文章。 顯示所有文章
顯示具有 python 標籤的文章。 顯示所有文章

Pyobjc project in Xcode 3.2+

Pyobjc project in Xcode 3.2+

XCode 3.2 拿掉了所有 python 和 ruby 的project樣本,也就是說不能直接開啟python 的專案了,原因是因為這些專案都沒有跟上xcode update的腳步,事實上除了新功能pyobjc一樣 可以運作無誤的。

不過想要開啟pyobjc的專案必須手動安裝 project template

下面是原文連結: http://ioanna.me/2009/09/installing-pyobjc-xcode-templates-in-snow-leopard/

Multiple version python in OSX

Multiple version python in OSX

如果您使用的是 Mac OSX 10.6 你又下載了新的 python 2.6.4 可能會有一個問題, 有些 model 變得找不到了..

這是因為如果shell環境沒有特別設定直接下載安裝 python 2.6.4 會裝在

/Library/Frameworks/Python.framework/Versions/2.6

原本 Snow Leopard 附帶的 2.6.1 在

/System/Library/Frameworks/Python.framework/Versions/2.6

如果沒有特別設定或是從新安裝 setuptools 透過 easy_install 安裝的 modle 會裝到

/Library/Python/2.6/site-packages

Python Introspection

Python Introspection

sys modules

  • 查詢目前所在的作業系統 (OS)
>>> import sys
>>> sys.platform
'darwin'
  • Max Int
>>> sys.maxint
2147483647

VIM python code complete

VIM python code complete

必要條件: Vim7 以上

  1. 安裝 pythoncomplete ( 丟到 autoload/ 下面)
  1. 確認你的 VIM 版本是有支援 python 的

    • macvim

      這討論串有相關說明 http://code.google.com/p/macvim/issues/detail?id=101 到此為止是 snap50 版本是已經建立好的 macvim 使用 python 2.5

    • Windows

      windows 要自己編譯 vim,其實也超級簡單的下載->編譯就好了,source code可以在 官方網頁下載。 這邊介紹使用 Visual Studio 編譯的指令 .. code-block:: bash

      nmake -f make_mvc.mak FEATURES=HUGE GUI=yes OLE=yes MBYTE=yes IME=yes GIME =yes PYTHON=C:python25 DYNAMIC_PYTHON=yes PYTHON_VER=25 CSCOPE=yes

確認 vim 有支援 python

:python import sys
:python print sys.version

PyPI upgrade (easy_install upgrade)

PyPI upgrade

PyPI setuptools (easy_install) 是目前最流行的 python 套件安裝工具,使用上非常簡單 直接執行

$ easy_install package_name

但是有一個問題,這個套件安裝工具有辦法像其他套件管理工具一樣,一個指令升級所有已經安裝的套件?

答案是肯定的,不過有點繞路就是了,不知道為什麼 easy_install 不內建 upgrade 機制..

  1. 安裝套件 yolk , yolk 是專門用來查詢已經安裝套件狀態的工具
$ easy_install yolk

大概簡單介紹一下 yolk option。

yolk -l --> 列出所有已經安裝的套件,active 代表可以import (在sys.path 中可以找到)

$ yolk -l
NoseGAE         - 0.1.4        - active
PIL             - 1.1.6        - active
Python          - 2.5.4        - active
html5lib        - 0.11.1       - active
ipython         - 0.10         - active
nose            - 0.11.1       - active
pyparsing-helper - 0.1.2        - active
pyparsing       - 1.5.2        - active
pysmell         - 0.7.3        - active
setuptools      - 0.6c11       - active
simplejson      - 2.0.9        - active
wsgiref         - 0.1.2        - active
yolk            - 0.4.1        - active

yolk -a --> 僅列出 active packages

yolk -U --> 列出需要更新的告件

yolk -F package_name --> 下載 package source code 到目前目錄

  1. 一個指令更新所有可更新套件( 需要 linux windows 系統請使用 cygwin 之類工具 )
$ yolk -U | cut -d ' ' -f 2 | xargs easy_install

IPython note (2)

IPython note (2)

第一集連結

http://psvsps2.blogspot.com/2009/05/ipython-study-note-1_25.html

doctest mode

doctest 是一個很棒的測試module,結合測試和說明加上直譯器驗證,想再Ipython 裡面產生 doctest 可以接受的測試程式碼,可以輸入 %doctest_mode

In [180]: %doctest_mode
*** Pasting of code with ">>>" or "..." has been enabled.
Exception reporting mode: Plain
Doctest mode is: ON
>>>

Input Cache System

IPython 會保存使用者的輸入和輸出資料 In/Out 簡單查看 In 和 Out 這兩個 list 就可了解他是幹嘛的了。

Input Cache 有定義一些 global object 請參考下面:

  1. _i : 上一個輸入
  2. _ii : 上上個輸入
  3. _i14 : In[14]
  4. %hist

_i 系列可以自由當成一般變數使用,比如拿來當字串列印:

In [145]: print ' [ '+_i142 + ' ] '
 [ _ip.magic("hist -g .*m1")
 ]

Exception

Python 丟出的exception因為會把整個進入function的堆疊依順序全部丟 出來,老實說就是丟了一大堆廢話,這點在IPython就有很明顯的改善, IPython不會丟出一推繁瑣的函式間的堆疊關係,除此之外還可以透過magic function xmode來設定exception的輸出。

xmode
設定Exception的輸出,有三種模式可以選擇分別是plain,verbose 和context,簡單來說plain呈現的資訊最少,context次之,verbose 最多,建議使用context比較能清楚了解exception發生地點的上下文關 係。

Debug

IPython 對於Debug也有一些方便的支援,沒有使用IPython的時候想要debug 程式,要在souce裡面加入pdb的code來執行pdb,如下例所示:

import pdb
a = 'message A'
pdb.set_trace()
# ...

IPython就不用這麼麻煩了,首先他有一個好用的magic function -> %pdb ,這個magic function可以打開/關閉IPython的automatic pdb功能,如果 automatic pdb = on,在exception丟出時候會自動執行pdb。

此外還可以配合%run -d來進入debug模式:

In [61]: run -d epdb1.py
Breakpoint 1 at /Users/janaustin/Code/python/epdb1.py:1
NOTE: Enter 'c' at the ipdb>  prompt to start your script.
> <string>(1)<module>()

ipdb> l

ipdb> n
> /Users/janaustin/Code/python/epdb1.py(1)<module>()
1---> 1 a='aaa'
      2 b='bbb'
      3 c='ccc'

Paste

在Note (1)有提到IPython可以透過%edit開啟外部編輯器來幫助輸入code, 可是寫程式除了用手慢慢打,剪下貼上也是十分常用的技能,IPython如果要貼上 程式片段,必須先下指令%cpaste進入剪貼模式,貼完後輸入'--'離開剪貼模式。

評估程式

有時候想要對程式的效率進行評估,IPython也貼新的提供可用的功能。

%time

計算執行的時間。

In [62]: %time sum(range(999999))
CPU times: user 0.27 s, sys: 0.02 s, total: 0.29 s
Wall time: 0.29 s
Out[63]: 499998500001L
%timeit

計算平均執行時間。

In [64]: %timeit sum(range(999999))
10 loops, best of 3: 277 ms per loop

macro

IPython 提供C/C++擁有的macro功能,macro可以

store save

UNITTEST in GAE

UNITTEST in GAE

Contents

Nose

Nose 可以自動收尋目錄下面所有的 python 檔案並執行 unittest,如果要在 本機端上面測試 google app engine 的程式,需要另外安裝 Nosegae_, Nosegae 會在本機建立好 google app engine 的環境,避免 import 錯誤。

這兩個都可以透過 easy_install 安裝:

easy_install nose

easy_install nosegae

Nosegae 預設的 google app engine 路徑是 /usr/local/google_appengine, 如果不是這個路徑可能需要在執行的時候傳入option (--gae-lib-root)

nosetests -v --with-gae --gae-lib-root="C:\Document and Setting\googleappengind"

接下來只要寫好測試模組即可,測試模組的檔案記得用test_xxxx.py這種格式。

Warning

在 Mac Snow Leopard 上一直會丟煩人的 LOG 不過應該是 GAE 的問題 root: INFO: zipimporter('/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/site-packages/setuptools-0.6c11-py2.5.egg', '') root: INFO: zipimporter('/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/site-packages/NoseGAE-0.1.4-py2.5.egg', '') root: DEBUG: Could not import "strop": Disallowed C-extension or built-in module

gaeunit.py

gaeunit.py 是專門為 google app engine 設計的測試架框,可以在網頁上面顯示測試結果。

使用上也十分簡單,下載 gaeunit.py 然後放到專案目錄下面,並在 app.yaml 加上:

- url: /test.*
  script: gaeunit.py

即可開始撰寫測試模組,可以在網址輸入 http://localhost:8080/test 閱讀測試報告。

也可以不要執行全部的測試,只要把想測試的模組名稱用url傳入即可:

Examples:

IPython study Note (1)

IPython study Note (1)

IPython的筆記,不確定哪時會寫(2)...

Magic Function

IPython 提供的好用特殊指令,想要知道提供的所有指令可以下達lsmagic,所有的magic function 在呼叫的時候請使用百分比'%'開頭,在global沒有名稱重複的情形下可以省略%。

Ex:無覆蓋pwd和有覆蓋pwd的情形

In [37]: pwd
Out[37]: '/Users/janaustin/Code/xxx'

In [38]: %pwd
Out[38]: '/Users/janaustin/Code/xxx'

In [39]: pwd=123

In [40]: pwd
Out[40]: 123

取得說明

學習任何一項事務說明文件要怎樣取得都是重要的,IPython中可以直接在單字後面加上'?'問號來取得 說明,也可以加上2個問號'??' 來取得更詳細的說明。

In [18]: lsmagic?
Type:                Magic function
Base Class:  <type 'instancemethod'>
String Form: <bound method InteractiveShell.magic_lsmagic of <IPython.iplib.InteractiveShell object at 0x484ff0>>
Namespace:   IPython internal
File:                /Library/Python/2.5/site-packages/ipython-0.9.1-py2.5.egg/IPython/Magic.py
Definition:  lsmagic(self, parameter_s='')
Docstring:
    List currently available magic functions.
%quickref
取得IPython的簡易說明。
%magic
取得magic的簡單說明。
help()
輸入指令help(),可以進入IPython一標題分類的說明系統,進入後輸入topic可以看到所有的 標題,在依照自己喜好深入閱讀。
help('標題')
直接跳至IPython提供的說明文件,比如help('for')
pdef funname

看函數的定義

In [13]: import re

In [14]: pdef re.match
 re.match(pattern, string, flags=0)
pdoc

顯示簡短的物件說明,(?說明的Description部份)

In [22]: pdoc os.path
Common operations on Posix pathnames.

Instead of importing this module directly, import os and refer to
this module as os.path.  The "os.path" name is an alias for this
module on Posix systems; on other systems (e.g. Mac, Windows),
os.path provides the same operations in a manner specific to that
platform, and is an alias to another module (e.g. macpath, ntpath).

Some of this can actually be useful on non-Posix systems too, e.g.
for manipulation of the pathname component of URLs.
pinfo obj
提供精確的定義和說明,和?提供的內容一致。
psource obj

顯示obj的source code。 (??說明的Source欄位)

In [26]: psource os.path.isdir
        def isdir(path):
            """Test whether a path is a directory"""
            try:
                st = os.stat(path)
            except os.error:
                return False
            return stat.S_ISDIR(st.st_mode)
pfile obj
直接開啟obj所在的檔案內容。

Local Variable相關的magic function

IPython 提供不少magic function幫助我們處理己定義的物件,像小弟使用這種直譯器的時候 常常卯起來亂設一些臨時的變數或是物件,這時候知道這些magic function有時候還滿有用的。

<tab>
IPython 執行時會自動載入<tab>補完功能,這個功能有涵蓋到區域變數和物件,對於懶得 打字的朋友算是滿有幫助的。
alias
和shell一樣的設定alias機制,可以設定系統指令。
who
列出所有存活的變數或是物件。
whos
列出所有存活的變數或是物件並提供更多資訊。
store
可以把變數或別名(alias)儲存起來,下次可以繼續使用,保存後改變的資料必須要在一次執行 store 指令,不然不會一起保存。
reset
將環境設定到一開始的執行狀態。
psearch
支援wildcard的收尋方式尋找變數或是物件。

外部Editor

IPython的設計者十分了解一個老練優秀的程式員一定要配上專用的Editor才能發揮最大的威力, 像我就一定要使用Vim或是emacs不然給我textmate也行,當然拉如果要開發cocoa程式我也接受 xcode...看來我並非老練優秀的程式員。

IPython 有一個edit的magic function,可以幫你開啟外部的editor,好吧開啟外部的editor 並沒什麼了不起的,當然他的特異功能不只這樣拉,待小弟慢慢道來。

改變預設的Editor

如果有設定環境變數 $EDITOR,IPython會依據$EDITOR的設定開啟外部編輯器,如果沒有設定 Linux/OSX會開啟VIM,Windows會打開小作家....別人怎麼想我是不知道拉,開小作家叫我打 程式還不如開個檔案說明我沒有設定喜歡的編輯器並且叫我設定,其實假如可以根本應該在安裝的 時候檢查有沒有gvim,ultraedito這些編輯器才對,開小作家真的太汙辱人惹...

OK這邊教你如何改變Windows竟然打開小作家的窘境,這邊的改法其實linux和osx一樣適用,所以 就不另外說明另外兩個真作業系統上面的改法了。

1.首先到 /Document and Settings/Administrator/_ipython下面找一個ipythonrc.ini 的檔案,假如沒上面目錄就找一下/Document and Settings/下面的/All Users或是登入名稱 的目錄下面有沒有,如果都沒有請確認是不是有設定 $HOME 環境變數,如果有設定的話應該會在 $HOME設定的目錄下。(linux/osx 在~/.ipython/ipythonrc)

2.在 ipythonrc.ini 裡面找到一行:

editor 0

改成

editor c:\vim\vim72\gvim.exe (填入想使用編輯器的路徑)

3.打完收工

編輯範例

In [4]: ed
IPython will make a temporary file named: /var/folders/iO/iODLAhjsHMiXw0jFf7Z3yU+++TI/-Tmp-/ipython_edit_MmSQ_n.py
Editing... done. Executing edited code...
Out[4]: "def edfun():\n    print 'editor defined function'\n\n"

上面例子首先輸入ed,iPython會打開編輯器,輸入完畢後存檔結束編輯IPython會 自動讀取,並執行剛剛輸入的資料。(下面是編輯器輸入的內容)

def edfun():
    print 'editor defined function'

如果不希望編輯完成後馬上執行,比如修改的是供程式呼叫的module,可以加上-x 選項(option)。

In [9]: ed -x edfun
Editing...

In [10]:

可以在ed後面加上參數,IPython會自動將source或是所在檔案開啟,請自行試試看 下面範例:

In [1]: import os

In [2]: ed -x os.path.isdir
Editing...

IPython打的好程式不想要重打

IPython 打好的程式不想重打怎辦?IPython提供一個magic function: hist可以列出 所有出入的內容。

In [8]: hist
1: _ip.magic("colors Linux")
2:
def myfun(a):
    for i in range(a):
        print i

如果覺得行號太礙眼可以加上-n選項(option)

In [8]: hist -n
_ip.magic("colors Linux")

def myfun(a):
    for i in range(a):
        print i

也可以濾掉magic function,只要加上-r選項即可。

edit指令也支援範圍操作:

edit 2:10 (將In[2]-In[10]取出並開啟外部編輯器編輯)

目錄的操作

IPython 的目錄操作沒什麼特別的,就是CD指令啪啪走,CD指令沒什麼好介紹的用法 windows和linux兩大系統的終端機都有,這邊介紹比較特別的指令。

bookmark
bookmark 可以替目錄取一個簡短的名稱。 比如要替當前目錄取名cw-> bookmark cw, 要替特定目錄上書籤-> bookmark bin /usr/local/bin

有了書籤就可以直接切換目錄,上例中設定的bin可以直接切換-> cd bin

Shell的互動

IPython不但是一個很好的python直譯器替代方案,他也是shell的替代方案,雖然 shell已經發展出許多不同的家族,如sh,C-Shell,bash等等,管理上shell script 也是大量被採用,但是如果你會python,小弟敢保證IPython絕對值得一試,威力 真的是強的和流氓一樣,唯一缺點可能就是要用你的script,必須裝上IPython吧。

Run Shell Command

開頭加上'!'

In [2]: !who
janaustin console   5 20 09:23
janaustin ttys001   5 25 16:00
janaustin ttys000   5 25 15:25
janaustin ttys002   5 25 16:39

如果要在shell command中使用python變數,只需要加上'$'

In [9]: !ls $pa
pass   pattn

In [9]: !ls $pattn
__init__.py   cdi_data.py      docCreator.py  go.py        rstView.py  test.py
adphelper.py  dataProvider.py  doceditor.py   ipython_log.py  rules.py         text_process.py
base_data.py  dmc.py        global.py      restwriter.py   setup.py    xml_data.py

python也可以接收shell command的輸出

In [14]: out = !ls
In [15]: out
Out[15]: SList (.p, .n, .l, .s, .grep(), .fields(), sort() available):
0: ADP
1: Python-3.0.1
2: Python-3.0.1.tgz
3: cocoa
4: docCreator
5: driverDoc.tmproj
6: firmware
7: gdata
8: graphicLib
9: hello.py
10: iPhone
11: pylint-0.15.2
12: python
13: rename.workflow
14: scripts
15: xml

懶人區

不知道是不是只有我會這樣,每次拿到新玩具第一個想知道的就是到底可以幫我省多少事,基本上 可以打一個自完成的事情我絕對不會考慮打兩個字,IPython到是提供了不少幫你少打字的功能。

<tab>
這說過了拉,就是補完~
print

print算是十分常用到的功能,IPython提共一個別名p,可以讓你少打4個字母喔

In [4]: msg = '12345'

    In [5]: p msg
    12345
呼叫fun

IPthon可以讓你省略括號...比如 fun(a,b)可以打成 fun a,b ,有點好笑可是真的 少打了兩個括號耶 XDDDDD。如果函式沒有參數,只要前面加上/,也可以省略後面的括號 ,比如show() -> /show。

In [1]: def funa(a,b):
   ...:     print a+b
   ...:
   ...:

In [2]: funa 1,2
------> funa(1,2)
3

In [3]: def show():
   ...:     print 'show'
   ...:
   ...:

In [4]: show
Out[4]: <function show at 0x4575f0>

In [5]: /show
------> show()
show

Python History

Python History

python 的作者 Guido van Rossum 開了一個講古的 blog_,內容十分有趣 python 為什麼 為長成今天這個樣子? 到底一開始是基於什麼理由 python 在第一次使用前不必宣告變數?

這個有趣的 blog 都有說道喔,其實下面的回應也滿精彩的 :)

看的我真是一把眼淚一把鼻涕阿~

...

Blogger auto poster

Blogger auto poster

長久以來都是笨笨的在 Blogger 提共的難用編輯視窗

https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgiVEcvMTVprz0vPwM1WKjlD35zdywRuojiKFcLE8serJYxs5KaHfAplzxKgSdVbZ0LDFhFrpXifvlDFOVUmXGSna9MPsA9kl5ZRXIc0DpiPNxem0BpF98gCA2mm8zju3S_RxTlM7DJMu1h/圖片%201.png

每次分享有關程式的文章,想要有漂亮的語法高亮度(syntax highligh)簡直要我的命,要先找個可以幫我把程式碼上色的東西 然後想辦法貼近我的文章中,非常討厭。

後來在 python 的世界裡面發現了 reStructruedText 這個神奇的玩意,他可以依據內定的簡單直覺規則將文字檔轉成 html 檔案, 這對我來說可是不得了得大躍進,再也不用忍受 Blogger 那一點都不好用的編輯視窗了,超爽!

玩了幾天後還是很懷念程式碼語法上色,當然 python 無所不包,一定有相關的module [1] 可以使用,果然讓我找到一個可以說 一勞永逸的解法 pygments ,幾乎檯面上超過一萬人使用過的程式語言或是 script 都有支援到~還不斷更新中,十分了不起, 因此我的 Blog 生活更開心了,可以產生有上色的程式碼就是炫!感覺就是專業!!現在我只要很簡單的打 rest 格式的內容,然後 用 rst2htmlc.py 轉成 html 在用瀏覽器打開,在複製貼上到 blogger 提共 的難用編輯視窗中即可...

說真的,這樣的確可以有美美的code syntax highlight,但好像很笨耶。

[1]module 把他想像成 C++ 世界的 Library 就好了,雖然差有點多...

環境建立

當然,我不是一個抱怨就可以貼一篇文章的人,當然有好方法提共才敢大聲,在 進入重點之前先把待會教學中必要的條件在這邊說明一下。

1. python os上最起碼要有 python 2.4 以上的版本,我自己是使用 python 2.5 至於更高級的版本等他 Third party library 都ok才考慮使用,所以沒有 測試過,不過應該可以使用 2to3 工具來簡單轉換,畢竟我也寫不出什麼超級 複雜的程式。

2. 不一定要裝,不過建議安裝一下 easy_install (python 方便的安裝 工具)。

3. BeautifulSoup 這套 Third party library ,很簡單拉就像裝一般 python library 一樣執行 setup.py install就好了(linux/osx 前面加 sudo)。

4. pygments 這是用來將 source code 作語法高亮度的library,可以到我 替 rst2htmlc.py 作的頁面看效果。

5. docutils 如果有安裝 easy_install 那就輸入 easy_install doctuils ,就會自行安裝了,不然請到連結處下載。

6. rst2htmlc.py 將這個檔案拷貝到執行目錄下面,並記得將權限設定可以 執行。

linux/osx 使用者無腦指令:

$sudo mv ./rst2htmlc.py /usr/local/bin
$chmod +x /usr/local/bin/rst2htmlc.py

Windows 的使用者可以參考 this 讓 windows command line 可以直接執行 python script。

7. post2blogger 小弟寫的懶人 post 程式,請自行修改下面程式碼,由於 牽扯到帳號密碼,所以自己改吧,也千萬拜託不要較我幫你改。

acc = 'xxx@gmail.com'  #你的 blogger 帳號
password = 'xxxxxx'     # 你的 blogger 密碼
name = 'your name'       # 你的作者名稱

都用好了就可以測試看看,打一篇符合reStructruedText 格式的文件,然後將 post2blogger.py 放到同一個目錄下面輸入下面的命令(xxxxx 是你的檔案名稱)

$ post2blogger.py xxxxx

post2blogger.py

#!/usr/bin/python
# encoding: utf-8
from __future__ import with_statement
"""
post2blogger.py

Created by Jan Austin on 2009-03-02.
"""

import sys
import os
import getopt
import gdata
import atom
import subprocess
from BeautifulSoup import BeautifulSoup

from gdata import service

acc = 'xxx@gmail.com'
password = 'xxxxxx'
name = 'your name'

help_message = '''
post2blogger auto generate html from rest text file and post to blogger.

post2blogger -ftest.txt
'''
class BloggerOperation(object):
    """ Provide blogger functions"""
    def __init__(self,email,pw):
        """Creates a GDataService and provides ClientLogin auth details to it.
        The email and password are required arguments for ClientLogin.  The
        'source' defined below is an arbitrary string, but should be used to
        reference your name or the name of your organization, the app name and
        version, with '-' between each of the three values."""

        # Authenticate using ClientLogin.
        self.service = service.GDataService(email, pw)
        self.service.source = 'Austin-post2blogger-1.0'
        self.service.service = 'blogger'
        self.service.account_type = 'GOOGLE'
        self.service.server = 'www.blogger.com'
        self.service.ProgrammaticLogin()

        # Get the blog ID for the first blog.
        feed = self.service.Get('/feeds/default/blogs')
        self_link = feed.entry[0].GetSelfLink()
        if self_link:
          self.blog_id = self_link.href.split('/')[-1]

    def CreatePost(self, title, content, author_name, is_draft):
        """This method creates a new post on a blog.  The new post can be stored as
        a draft or published based on the value of the is_draft parameter.  The
        method creates an GDataEntry for the new post using the title, content,
        author_name and is_draft parameters.  With is_draft, True saves the post as
        a draft, while False publishes the post.  Then it uses the given
        GDataService to insert the new post.  If the insertion is successful, the
        added post (GDataEntry) will be returned.
        """

        # Create the entry to insert.

        entry = gdata.GDataEntry()
        entry.author.append(atom.Author(atom.Name(text=author_name)))
        entry.title = atom.Title(title_type='xhtml', text=title)
        entry.content = atom.Content(content_type='html', text=content)
        if is_draft:
          control = atom.Control()
          control.draft = atom.Draft(text='yes')
          entry.control = control

        # Ask the service to insert the new entry.
        return self.service.Post(entry,
          '/feeds/' + self.blog_id + '/posts/default')


class Usage(Exception):
    def __init__(self, msg):
        self.msg = msg

def get_blogger_html(htmlfile):
    """docstring for get_blogger_html"""
    with open(htmlfile) as f:
        html = f.read()
        soup = BeautifulSoup(html)

        if soup.title:
            title = soup.title.string
        else:
            title = soup.h1.string
        print title
        return title, unicode(soup.div)

def run(inputfile):
    """docstring for run"""
    pwd = os.getcwd()
    inputfile = os.path.join(pwd,inputfile)
    print 'rest 2 html.....'
    cmd = 'rst2htmlc.py %s test.html'%inputfile
    subprocess.call([cmd],shell=True)
    print 'rest 2 html done.'
    print 'Get html snippet...'
    title,content = get_blogger_html('test.html')
    print 'Get html snippet done.'

    print 'Connect blogger server.....'
    blogger = BloggerOperation(acc,password)
    print 'Connected blogger server.'
    author_name = name
    print 'Send content to blogger server...'
    blogger.CreatePost(title,content.encode('utf-8'),author_name,True)
    print 'All Done.'



def main(argv=None):
    if argv is None:
        argv = sys.argv
    try:
        try:
            opts, args = getopt.getopt(argv[1:], "hf:v", ["help", "file="])
        except getopt.error, msg:
            raise Usage(msg)

        # option processing
        for option, value in opts:
            if option == "-v":
                verbose = True
            if option in ("-h", "--help"):
                raise Usage(help_message)
            #if option in ("-f", "--file"):
            #    inputfile = value
        if len(args) == 1:
            print args
            inputfile = args[0]
            run(inputfile)
        else:
            Usage(help_message)

    except Usage, err:
        print >> sys.stderr, sys.argv[0].split("/")[-1] + ": " + str(err.msg)
        print >> sys.stderr, "\t for help use --help"
        return 2


if __name__ == "__main__":
    sys.exit(main())

rst2htmlc.py

#!/usr/bin/python

# Author: Chris Liechti
# Contact: cliechti@gmx.net
# Revision: $Revision$
# Date: $Date$
# Copyright: This module has been placed in the public domain.

"""
A minimal front end to the Docutils Publisher, producing HTML slides using
the S5 template system.
"""

try:
    import locale
    locale.setlocale(locale.LC_ALL, '')
except:
    pass

import pygments
from pygments.lexers import get_lexer_by_name
from pygments.formatters import get_formatter_by_name
from docutils.parsers import rst
from docutils import nodes
from docutils.writers.html4css1 import Writer, HTMLTranslator

class DocorateHeadHTMLTranslator(HTMLTranslator):
    _classText = "docutils"

    def __init__(self, document):
        HTMLTranslator.__init__(self,document)
        self.head_suffix = ['','','','']
        self.body_prefix = []
        self.body_suffix = []
        self.stylesheet = []

    def visit_document(self, node):
        self.head.append('<h1 class="%s" >%s</h1>\n'
                         % (self._classText, self.encode(node.get('title', ''))))

    def visit_title(self, node):
        """Only 6 section levels are supported by HTML."""
        check_id = 0
        close_tag = '</p>\n'
        if isinstance(node.parent, nodes.topic):
            self.body.append(
                  self.starttag(node, 'p', '', CLASS='topic-title first'))
        elif isinstance(node.parent, nodes.sidebar):
            self.body.append(
                  self.starttag(node, 'p', '', CLASS='sidebar-title'))
        elif isinstance(node.parent, nodes.Admonition):
            self.body.append(
                  self.starttag(node, 'p', '', CLASS='admonition-title'))
        elif isinstance(node.parent, nodes.table):
            self.body.append(
                  self.starttag(node, 'caption', ''))
            close_tag = '</caption>\n'
        elif isinstance(node.parent, nodes.document):
            self.body.append(self.starttag(node, 'h1', '', CLASS=self._classText))
            close_tag = '</h1>\n'
            self.in_document_title = len(self.body)
        else:
            assert isinstance(node.parent, nodes.section)
            h_level = self.section_level + self.initial_header_level - 1
            atts = {}
            if (len(node.parent) >= 2 and
                isinstance(node.parent[1], nodes.subtitle)):
                atts['CLASS'] = 'with-subtitle'
            atts['CLASS'] = self._classText
            self.body.append(
                  self.starttag(node, 'h%s' % h_level, '', **atts))
            atts = {}
            if node.hasattr('refid'):
                atts['class'] = 'toc-backref'
                atts['href'] = '#' + node['refid']
            if atts:
                self.body.append(self.starttag({}, 'a', '', **atts))
                close_tag = '</a></h%s>\n' % (h_level)
            else:
                close_tag = '</h%s>\n' % (h_level)
        self.context.append(close_tag)

    def visit_subtitle(self, node):
        if isinstance(node.parent, nodes.sidebar):
            self.body.append(self.starttag(node, 'p', '',
                                           CLASS='sidebar-subtitle'))
            self.context.append('</p>\n')
        elif isinstance(node.parent, nodes.document):
            self.body.append(self.starttag(node, 'h2', '', CLASS=self._classText))
            self.context.append('</h2>\n')
            self.in_document_title = len(self.body)
        elif isinstance(node.parent, nodes.section):
            tag = 'h%s' % (self.section_level + self.initial_header_level - 1)
            self.body.append(
                self.starttag(node, tag, '', CLASS=self._classText) +
                self.starttag({}, 'span', '', CLASS=self._classText))
            self.context.append('</span></%s>\n' % tag)


_w = Writer()
_w.translator_class = DocorateHeadHTMLTranslator

def code_formatter(language, content):
    lexer = get_lexer_by_name(language)
    formatter = get_formatter_by_name('html', noclasses=True)
    html = pygments.highlight(content, lexer, formatter)
    return nodes.raw('', html, format='html')

def code_role(name, rawtext, text, lineno, inliner, options={},
              content=[]):
    language = options.get('language')
    if not language:
        args  = text.split(':', 1)
        language = args[0]
        if len(args) == 2:
            text = args[1]
        else:
            text = ''
    reference = code_formatter(language, text)
    return [reference], []

def code_block(name, arguments, options, content, lineno,
               content_offset, block_text, state, state_machine):
    """
    Create a code-block directive for docutils.

    Usage: .. code-block:: language

    If the language can be syntax highlighted it will be.
    """
    language = arguments[0]
    text = '\n'.join(content)
    reference = code_formatter(language, text)
    return [reference]

# These are documented
# at http://docutils.sourceforge.net/spec/howto/rst-directives.html.
code_block.arguments = (
    1, # Number of required arguments.
    0, # Number of optional arguments.
    0) # True if final argument may contain whitespace.

# A mapping from option name to conversion function.
code_role.options = code_block.options = {
    'language' :
    rst.directives.unchanged # Return the text argument, unchanged
}
code_block.content = 1 # True if content is allowed.
# Register the directive with docutils.
rst.directives.register_directive('code-block', code_block)
rst.roles.register_local_role('code-block', code_role)


from docutils.core import publish_cmdline, default_description

description = ('Generates HTML documents from standalone '
               'reStructuredText sources.  ' + default_description)

#publish_cmdline(writer_name='html', description=description)
publish_cmdline(writer=_w , description=description)

Google blogger data API

Google blogger data API

Google公佈讓python client端存取blogger資訊的library.

  1. Document

安裝環境

  1. python, 請到官網尋找對應os的安裝方式。( http://www.python.org )
  2. 安裝 ElementTree (python 2.5 之前的版本才需要)
  3. 安裝 Google data library

Hello gdata

列出所有 google document 文件的範例,ClientLogin() 部份請改成合法的帳號密碼.

import gdata.docs.service# Create a client class which will make HTTP requests with Google Docs server.client = gdata.docs.service.DocsService()# Authenticate using your Google Docs email address and password.client.ClientLogin('accound@gmail.com', 'password')# Query the server for an Atom feed containing a list of your documents.documents_feed = client.GetDocumentListFeed()# Loop through the feed and extract each document entry.for document_entry in documents_feed.entry:  # Display the title of the document on the command line.  t = document_entry.title.text.decode('utf-8')  print t.encode('utf-8')

Docutils configure

docutils 設定資料

Configuration Files

doctuils [1] 可以把設定寫成一個設定檔案,然後讓所有的 Front-End Tools 自動遵循設定檔 的規範,設定檔涵蓋所有內建的預設值,和命列列的選項,有三個預設的設定檔:

  1. /etc/docutils.conf: 全系統共用的設定檔。
  2. ./docutils.conf: 目前目錄的設定檔,可以想像成專案使用的設定檔。
  3. ~/.docutils: 使用者等級的設定檔。

使用順序依序為: 使用者等級 -> 目前目錄等級 -> 全系統。

設定檔語法

首先,預設開啟檔案的編碼為utf-8,為了不要要的困擾建議設定檔使用utf-8編碼。

設定檔由數個 section 組成,每個 section 開始那列都是 [section] ,然後接一連串 "name:value" 的設定值(也可以寫成 name=value)。

每一列開頭為"#"或";"(井號或分號)代表註解,程式會忽略他。

Example:

# These entries affect all processing:
[general]
source-link: yes
datestamp: %Y-%m-%d %H:%M UTC
generator: on
 
# These entries affect HTML output:
[html4css1 writer]
# Required for docutils-update, the website build system:
stylesheet-path: ../docutils/writers/html4css1/html4css1.css
embed-stylesheet: no
field-name-limit: 20

General Setting

footnote_backlinks

允許 footnote 可以連回引用處 (citation),預設為 Enable.

generator

在文件的註腳加入 "Generated by Docutils" ,預設為 off. Options [2]:--generator, -g, --no-generator .
record_dependencies
輸出 dependen file list 到指定的檔案。 Default: None. Option: --record-dependencies=<file>.
report_level
Verbosity threshold at or above which system messages are reported. Default: warning (2). Options: --report, -r, --verbose, -v, --quiet, -q.
sectnum_xform
Enable or disable the section numbering transform (docutils.transforms.parts.SectNum). Default: enabled (1). Options: --section-numbering, --no-section-numbering.
source_link
Include a "View document source" link in the document footer. URL will be relative to the destination. Default: don't (None). Options: --source-link, -s, --no-source-link.
[1]reStructuredText front-end tools.
[2]command line options

(PEP 328) Absolute import

import的兩個問題

  1. 複雜package的import太過冗長.
  2. package內的import可能出現模擬兩可的情形,當package和收尋path有相同名稱的module 時,必須有明確的機制決議.

python 2.4之後現在可以不需要將冗長的import敘述會了好看拆成拆成兩行了(如下)

# before python 2.4
from Tkinter import Tk, Frame, Button, Entry, Canvas
form Tkinter import Text, LEFT, DISABLED, RIDGE

# after python 2.4
from Tkinter import (Tk, Frame, Button, Entrym Convas,
   Text, LEFT, DISABLED, RIDGE)

從python 2.5 開始可以使用新的import方式,在2.5需要明確載入.

from __future__ import absolute_import

使用 absolute_import 後就必須以'絕對路徑'來import module, 也就是說package內

import foo

是不合法的, 必須要使用絕對路徑ex:

# 類似下面的絕對路徑
import mypackage.function1.foo

閒麻煩的畫可以使用 relative imports,

from .foo import bar

from . import foo

python -- partial function application

PEP 309 提議了 python 的 PFA 行為.

這觀念是由Functional Language衍生來的, 提供一種讓function參數遞減至只剩一個的方法 [1], 其實一開始我也不是很了解他到底要表達什麼... 讓function的參數變少有那麼了不起嗎?

Python的實作範例,簡單來說就是實作出一個class接受function和一串function argument作為 constructor的參數並保存下來, 然後class override call operator,所以class instance 可以像function一樣的使用.

class partial(object):
  def __init__(*args, **kw):
      self = args[0]
      self.fn, self.args, self.kw = (args[1], args[2:], kw)

  def __call__(self, *args, **kw):
      if kw and self.kw:
          d = self.kw.copy()
          d.update(kw)
      else:
          d = kw or self.kw
      # 合併args和keyword args,作為self.fn的參數
      # 傳回 self.fn
      return self.fn(*(self.args+args), **d)

看一個例子

>>> from os import path as p
>>> from functools import partial
>>> joinhome = partial(p.join, '/usr/home')
>>> # 建立絕對路徑
>>> joinhome('myfile')
'/usr/home/myfile'

很像default argument做的事情, 不過更靈活更好用, 尤其 python 有 argument 可以不照順序 傳遞的規則, 所以給予 partial function 的彈性和運用更寬更好用.

[1]Function curring

Apache + mod_python 安裝筆記

安裝

在 ubuntu 上安裝 apache 沒有遇到什麼問題, 造說明來作很簡單一下就做好了, 啟動時 候記得要使用 root 權限, 非 root 權限沒有 listen port 80 的權限.

% sudo apachectl start

mod_python

mod_python 在 configure 的時候由於我的 python 2.5 是使用 ubuntu package安裝 的, 似乎沒有他要的 head file..

  • 去套件管理程式把python2.5 develop package 裝上.. 就OK了, 不然去抓source然後 自己make install也一樣會得到 build mod_python 要使用的檔案.

搞定 python 後, configure 還是有 flex warring... 我裝就是了, 裝完後果然沒有 warring了...這不是廢話嗎?

% make

還是有問題,怎麼這麼不順阿, mod_pytho 的 mail-list 有找到相關說明, 假如你的error 也是長這樣.

> structure or union
> apxs:Error: Command failed with rc=65536
> .
> make[1]: *** [mod_python.so] Error 1
> make[1]: Leaving directory `/root/mod_python-3.3.1/src'

請使用svn check out 新的fix版本.

% svn co https://svn.apache.org/repos/asf/quetzalcoatl/mod_python/trunk/ mod_python

接下來當然是執行 sudo make install, 請注意他吐出來的訊息, 開頭部份告訴你呆會怎樣設定 Apache, 下面是我的電腦吐出來的訊息

Performing DSO installation.

/usr/bin/install -c -d /usr/local/apache2/modules
/usr/bin/install -c src/mod_python.so /usr/local/apache2/modules

Now don't forget to edit your main config and add
   LoadModule python_module /usr/local/apache2/modules/mod_python.so
and if your configuration uses ClearModuleList, then also
   AddModule mod_python.c

最後再去 apache安裝目錄/conf/http.conf 加上剛剛make install告訴你要加的就好了.. 這邊為了待會的測試我順到一起加上了directives.

#Direct mod_python
LoadModule python_module /usr/local/apache2/modules/mod_python.so
#Test mod_python , 因為blogger很笨我必須要避開語法
#複製貼上時下面 [ 請用 < 取代
[Directory /Apace安裝目錄/htdocs/test>
       AddHandler mod_python .py
       PythonHandler mptest
       PythonDebug On
[Directory>

測試 mod_python 是否裝好, 到你的site下面(通常是 apache安裝目錄/htdocs) 建立 test

% mkdir test

建立測試的python檔案 mptest.py

from mod_python import apache

def handler(req):
   req.content_type = 'text/plain'
   req.write("Hello World!")
   return apache.OK

網址輸入 http://127.0.1.1/test/mptest.py

應該會看到東西...(Hello World!)

Document python (1)

這邊介紹的是符合python2.6之後文件建議的格式以及使用的Sphinx專有的一些額外的設定.

Paragraphs

Paragraphs用句號結束並使用blank line來分隔paragraph.

List and Quotes

Sphinx並沒有增加什麼新的設定,列舉簡單例子.

* This is a bulleted list.
* It has two items, the second
 item uses two lines.

1. This is a numbered list.
2. It has two items too.

#. This is a numbered list.
#. It has two items too.

Sphinx在List部份沒有增加新的功能,可是刪減了字母list.

A. First item
B. Second item

(上面在sphinx是行不通的)

巢狀list在sphinx中也有一點改變, 每個level間要使用blank line分開,請見下例.

* this is
* a list

 * with a nested list
 * and some subitems

* and here the parent list continues

Definition list沒有特別的改變.

term (up to a line of text)
  Definition of the term, which must be indented

  and can even consist of multiple paragraphs

next term
  Description.

Source Code

Sphinx 通常使用 Literal code block 來描述 source code.

Literal code block 沒有變化一樣是由"::"定義下一個block表示Literal code block.

This is a normal text paragraph. The next paragraph is a code sample::

   It is not processed in any way, except
   that the indentation is removed.

   It can span multiple lines.

This is a normal text paragraph again.

Directives

.. function:: foo(x)
          foo(y, z)
  :bar: no

  Return a line of text input from the user.

上例中 function 是 directive name. 代有兩個參數 foo(x) 和 foo(y, z), directive 後面要接一個blank line 作為分隔.

Footnotes

[#]_ 代表footnote, 請劍下例.

Lorem ipsum [#]_ dolor sit amet ... [#]_

.. rubric:: Footnotes

.. [#] Text of the first footnote.
.. [#] Text of the second footnote.

Note

也可以使用明確的數字代替井號.

Related Posts with Thumbnails