Livespace要在明年關(guān)閉了,搭建了micolog在google app engine,方便以后自己掙騰。上次用生拙的C#寫(xiě)個(gè)live space到livespace的博客遷移工具,使用metaweblog接口,見(jiàn)?Live Spaces新舊空間遷移方法 。上次使用getRecentPosts函數(shù)依次取得最近的一篇,然后存檔后發(fā)表后,刪除。這次通過(guò)正則表達(dá)式分析網(wǎng)頁(yè)內(nèi)容,獲取到postid后,再使有g(shù)etPost接口獲取文章,再進(jìn)行發(fā)表,而且這次使用python寫(xiě)成的。
metaweblog的內(nèi)容不再敘述,其實(shí)這個(gè)協(xié)議寫(xiě)得真不怎么樣,沒(méi)有檢索文章的接口,要讓人硬生生地從網(wǎng)頁(yè)中分析出postid來(lái)。因此解析postid是這個(gè)遷移工具的重要內(nèi)容。
#獲取www.shnenglu.com樣式的postid列表
def getCppblogId(blog):
url='http://www.shnenglu.com/'+blog['user']+'/default.html?page=1&OnlyTitle=1'
urlfile = urllib.urlopen(url)
html = urlfile.read()
#獲取存檔頁(yè)碼數(shù)
pattern = re.compile(r'http://www.shnenglu.com/'+blog['user']+'/default.html\?page=(\d+)&OnlyTitle=1')
pages = [1]
pages += pattern.findall(html)
ids=[]
for p in pages:
url= 'http://www.shnenglu.com/'+blog['user']+'/default.html?page='+str(p)+'&OnlyTitle=1'
urlfile = urllib.urlopen(url)
html = urlfile.read()
pattern = re.compile(r'http://www.shnenglu.com/'+blog['user']+'/admin/EditPosts.aspx\?postid=(\d+)')
id = pattern.findall(html)
ids += id
return ids
利用存檔頁(yè)面得到總共頁(yè)數(shù)(或許頁(yè)數(shù)多了或有問(wèn)題,未驗(yàn)證),然后在每頁(yè)解析出postid,cppblog較簡(jiǎn)單
def getLivespaceId(blog):
ids=[]
url=blog['user']+'.spaces.live.com/blog/'
i=0
while True:
url='http://'+url
urlfile = urllib.urlopen(url)
html = urlfile.read()
#print html
pattern = re.compile(r'entrycns!'+'([a-zA-Z0-9!]*)')
id = pattern.findall(html)
ids += id
pattern = re.compile(blog['user']+'.{1,50}pagedir=Next[^"]*')
urls = pattern.findall(html)
i=i+1
if len(urls) ==0:
break
url = unescape(urls[0])
return ids
live space沒(méi)有總共的頁(yè)數(shù),只能一直next下去,發(fā)現(xiàn)沒(méi)有next按鈕了就停止,在每頁(yè)再解析出postid來(lái),unescape是自定義函數(shù),目的是將html編碼轉(zhuǎn)換為像!等符號(hào)。
在遷移post時(shí)出現(xiàn)未micolog中定義的目錄(category)會(huì)出錯(cuò),因此遷移工具里如果碰到未定義過(guò)的類(lèi)別,會(huì)自動(dòng)舍棄掉。因此在使用
時(shí)需要在micolog里定義原先blog的類(lèi)別,以致不會(huì)出現(xiàn)目錄丟失的現(xiàn)象。此遷移工具在python2.5下完成,只要在源碼中修改中開(kāi)頭的
srcBlog和dstBlog定義里的用戶(hù)名,密碼,webapi即可使用。源碼中還實(shí)現(xiàn)BlogXML類(lèi),用于存檔為xml格式,但未用于主程序中。
遷移工具源碼
網(wǎng)絡(luò)書(shū)簽自從del.icio.us推出后,各個(gè)網(wǎng)絡(luò)巨頭都推出了相應(yīng)的服務(wù),對(duì)于各個(gè)書(shū)簽服務(wù),我針對(duì)了自己的情況進(jìn)行了一番小調(diào)查后,確定下用google bookmarks服務(wù)。雖然del.icio.us美味書(shū)簽最早推出,并有些特別的工功能,有著很大的用戶(hù)群,但是我感覺(jué)它更偏向社交化的web服務(wù),如將好的書(shū)簽共享等,有著好友的功能,而我更偏向于需要一種簡(jiǎn)潔的書(shū)簽存儲(chǔ)功能。再有就是美味書(shū)簽改版,對(duì)于網(wǎng)絡(luò)安全功能過(guò)于注重,導(dǎo)致一種不好的用戶(hù)體驗(yàn),比如密碼要數(shù)字字母混合,并且不能與用戶(hù)名有太多重合等,還有密碼最多線(xiàn)上保存兩周。這些安全措施我都知道,但比一些公司密碼管理還嚴(yán),這至于嗎?
國(guó)內(nèi)的也出現(xiàn)了許多對(duì)應(yīng)的web 2.0的網(wǎng)站,但是我沒(méi)試用。還有一個(gè)選擇就是baidu的搜藏,除了網(wǎng)頁(yè)快照這個(gè)功能比較吸人外,其他并無(wú)亮點(diǎn)。最早看中g(shù)oogle書(shū)簽是因?yàn)樗拈_(kāi)放性,比如搜藏都沒(méi)有導(dǎo)出功能,而google就有導(dǎo)出,不怕用戶(hù)流失,這一點(diǎn)蠻贊的。但是就其本身來(lái)說(shuō),使用并不方便,后來(lái)我使用了一直比較反感的工具條后,又開(kāi)始使用它的書(shū)簽,除了添加方便以外,整理和查找功能都比較薄弱。比如在線(xiàn)上,不能直接拖拽進(jìn)行標(biāo)簽的分類(lèi),要手工點(diǎn)擊編輯。google對(duì)這個(gè)服務(wù)不怎么看中,自推出以后,沒(méi)有什么新的功能增加,希望以后有類(lèi)似網(wǎng)頁(yè)快照的存檔功能就好了。
現(xiàn)在使用firefox3瀏覽器后,找到了GMarks插件,它能直接存取google書(shū)簽,包含一個(gè)邊欄,工具欄,和一個(gè)書(shū)簽快速查找框,可進(jìn)行批量修改,刪除書(shū)簽,刪除標(biāo)簽等等功能。它也可以在沒(méi)有安裝google工具條的情況下使用,還有定制工具欄等,最妙的是有了google工具條中沒(méi)有的查找功能,不然在上千條書(shū)簽找到你需要的,那是有點(diǎn)兒困難的。現(xiàn)在我將自己的收藏全都保存到google書(shū)簽了,這樣以后重裝系統(tǒng),再不用做備份了,而且在不同的機(jī)子上都可以用。
順便說(shuō)下,如何將FF3的書(shū)簽導(dǎo)入到google書(shū)簽服務(wù)中,那就使用google工具條,里面書(shū)簽選項(xiàng)里有導(dǎo)入功能的,很簡(jiǎn)單。
微軟啟用了新的live域名,有許多人將hotmail之類(lèi)的帳號(hào)轉(zhuǎn)到新的域名,這就出現(xiàn)了如何將原帳號(hào)下的個(gè)人信息轉(zhuǎn)移到新帳號(hào)的問(wèn)題。對(duì)于live messager的聯(lián)系人列表可采用其聯(lián)系人選項(xiàng)中的導(dǎo)入導(dǎo)出功能,而最麻煩當(dāng)屬將live spaces的空間博客轉(zhuǎn)移到新的帳號(hào)名下。最直接方法就是聯(lián)系微軟管理員,將你舊帳號(hào)下的空間所有權(quán)轉(zhuǎn)移到新帳號(hào)名下,但是業(yè)務(wù)上是否可行不得而知。因此轉(zhuǎn)而另一方法,開(kāi)新的空間,將舊空間的博客轉(zhuǎn)移到新空間來(lái),本文就是采用這種思路,順帶提及下live api的簡(jiǎn)單使用。
Windows Live Spaces MetaWeblog API提供了給外部程序進(jìn)行文章內(nèi)容設(shè)置和讀取的功能。API使用了XML—RPC協(xié)議來(lái)在客戶(hù)端應(yīng)用程序與Weblog服務(wù)器端進(jìn)行通訊。
為了使用MetaWeblog API編輯空間中的博文內(nèi)容,首先需要在空間啟用E-mail發(fā)布功能,并設(shè)置密碼字。
- 到你的空間中的Options->E-mail Publishing選項(xiàng)進(jìn)行配置
- 打開(kāi)E-mail發(fā)布功能,并選擇 secred word的密碼字。
在程序中會(huì)用到用戶(hù)名和密碼,如果你的空間地址為: oldname.spaces.live.com,則用戶(hù)名就是oldname,而不是你的live id,密碼則是上面設(shè)置的secred word,而不是live id的密碼。
現(xiàn)在的MetaWeblogApi能進(jìn)行發(fā)布新博文,編輯現(xiàn)有的博文,獲取指定博文,獲取類(lèi)別列表,獲取最近發(fā)布的博文,刪除博文,獲取用戶(hù)博客信息,獲取用戶(hù)信息等功能。由這些功能,想遷移博客內(nèi)容,首先需要獲取到舊空間里的博文。我們自然想到用MetaWeblogAPI metaWeblog.getRecentPosts Method函數(shù),指定一個(gè)較大的值,然后獲取全部的博文。很可惜,對(duì)于live spaces值只能取20,也就是說(shuō)只能獲取最近20篇博文。順便提下,這里的20篇包括你己發(fā)布的,和存在空間里的草稿,這些草稿有時(shí)候并不會(huì)在空間里顯示出來(lái),但是操作時(shí)會(huì)有表示。如果用MetaWeblogAPI metaWeblog.getPost Method,需要知道指定博文的id號(hào),沒(méi)有獲取到全部博文id的方法作輔助,這又是一個(gè)因難。
最后我采用了將metaWeblog.getRecentPosts方法的獲取值設(shè)為1,每次取最近的一篇博文,然后記錄id號(hào),將這博文用MetaWeblogAPI metaWeblog.newPost Method發(fā)表到新空間,然后用MetaWeblogAPI blogger.deletePost Method將這id號(hào)的博文從舊空間中刪去,重復(fù)進(jìn)行,直到無(wú)法從舊空間里獲取到博文。在程序?qū)崿F(xiàn)借用了MSDN中的示例,為了防止網(wǎng)絡(luò)故障之類(lèi)以及做了備份,先是將獲取博文內(nèi)容寫(xiě)到本地文件,再進(jìn)行刪除。
程序中還要說(shuō)明的是,由于live spaces服務(wù)器使用非標(biāo)準(zhǔn)的時(shí)間格式,造成用DateTime.Now和獲取到的博文的dateCreated都是"1/1/0001 12:00:00 AM"的格式,這需要在Invoke方法調(diào)用前加上this.NonStandard = XmlRpcNonStandard.AllowNonStandardDateTime語(yǔ)句。還有需要用到CookComputing.XmlRpcV2.dll,它實(shí)現(xiàn)了.net 2.0版本的XML-RPC協(xié)議,己包含在文末的源碼中。如果是.net 1.1,需要其他相應(yīng)的文件,可具體參見(jiàn)http://www.xmlrpc.com/metaWeblogApi。
最后要提下的是,程序只用于我自己的空間遷移,再加上不懂C#,用戶(hù)名和密碼之類(lèi)都硬編碼了,MetaWeblog之類(lèi)的方法也應(yīng)能用于像cppblog之類(lèi)用wordpress的博客空間。這些部分加之完善,應(yīng)能做個(gè)博客搬家工具的。
參考:
文中的遷移工具源碼下載
MDSN Windows Live Spaces SDKs
Google的chrome瀏覽器一出來(lái),我就被它的簡(jiǎn)潔風(fēng)格給吸引住了,試用了幾天,總體上還不錯(cuò)。但是還有幾個(gè)問(wèn)題,一是擴(kuò)展太少,用些地方用起來(lái)不方便,像它自家的google工具欄都還沒(méi)有開(kāi)始支持。二是有時(shí)候在切換tab的時(shí)候,感覺(jué)有明顯的停滯感,不知是否是多進(jìn)程切換的原因,三是還有些網(wǎng)站不支持chrome。
因?yàn)檫@些種種原因,我切換回了firefox 3。對(duì)于ff3,我也是剛剛用,但是越用越順手,特別是插件機(jī)制,可以把玩好長(zhǎng)時(shí)間。正像別人說(shuō)過(guò)的那樣,沒(méi)有插件的ff3,還不如IE呢。于是通過(guò)設(shè)置,將自己的Firefox打造成了chrome風(fēng)格,先上全屏截圖,初始頁(yè)是快速撥號(hào),因?yàn)殡[私關(guān)系,把它們都復(fù)位了,效果跟chrome差不多的。
下面介紹簡(jiǎn)要操作步驟:
1、Chrome主題風(fēng)格 Chromifox是仿Chrome的主題,現(xiàn)處于實(shí)驗(yàn)版本階段,因此下載安載需要以網(wǎng)站注冊(cè)用戶(hù)的身份登陸。下載地址為:https://addons.mozilla.org/en-US/firefox/addon/8782
2、去除菜單欄 需要安裝Compact Menu 2的插件,它可以定制原來(lái)的菜單欄為單個(gè)按鈕或圖標(biāo)。下載地址為:https://addons.mozilla.org/en-US/firefox/addon/4550
3、去除標(biāo)題欄 這工作稍微有點(diǎn)兒麻煩,需要一個(gè)插件和一個(gè)腳本。Custom Buttons 2擴(kuò)展提供創(chuàng)建,維護(hù),導(dǎo)入,導(dǎo)出工具欄按鈕的基礎(chǔ)代碼,也就是你可以用javascript代碼寫(xiě)些特定用途的按鈕。下載地址為:https://addons.mozilla.org/en-US/firefox/addon/5066。安裝完成后,再使用一個(gè)為隱藏標(biāo)題欄而定制的腳本,地址為:http://custombuttons2.com/forum/viewtopic.php?f=35&t=523,點(diǎn)擊其中的Toggle Chrome鏈接和Toggle Chrome/Maximized,即可安裝。
4、隱藏狀態(tài)欄 無(wú)需任何插件,只需菜單欄的“查看”中的“狀態(tài)欄”不要勾選上即可。
5、快速撥號(hào) Speed Dial和Fast Dial這兩個(gè)插件均能提供,我現(xiàn)使用Speed Dial,地址為https://addons.mozilla.org/en-US/firefox/addon/4810,另Fast Dial的地址為https://addons.mozilla.org/en-US/firefox/addon/5721。
其他諸如隱身模式、下載狀態(tài)欄、將網(wǎng)站轉(zhuǎn)換為獨(dú)立的應(yīng)用程序都可實(shí)現(xiàn),具體可參見(jiàn):http://www.cnbeta.com/articles/64031.htm
我的擴(kuò)展列表
附帶我在用的一些有用的插件功能,對(duì)于一般的用戶(hù)來(lái)講,這些功能也會(huì)大大節(jié)省你的時(shí)間,提高你上網(wǎng)瀏覽的體驗(yàn)。這些可能是最基本的,高級(jí)的要隨你自己,你的地盤(pán),你做主。
IE Tab 有些網(wǎng)站不支持非IE內(nèi)核的怎么辦,先不要有抱怨,有了它讓你自由切換到IE的內(nèi)核,但是外部功能不會(huì)減少,必備
FireGestures 鼠標(biāo)手勢(shì),我是從Maxthon轉(zhuǎn)過(guò)來(lái)的,這個(gè)功能太好用了。這個(gè)插件更強(qiáng)大,可以Tab,按鍵,滾輪上都可應(yīng)用
Easy Dragtogo 類(lèi)似于鼠標(biāo)手勢(shì),有些超鏈接只要一拖,就可按設(shè)置在新tab或在另一tab打開(kāi),不需要再用右鍵了。我對(duì)FireGestures還不熟,不知道這功能是否可用FireGestures代替,這功能現(xiàn)在還需要
Flashgot 文件下載管理,我用于管理flashget工具,內(nèi)置支持許多下載工具
Adblock 沒(méi)有廣告的世界真清靜,雖然Firefox自身的攔截能力己經(jīng)很強(qiáng)了,但是它提供更強(qiáng)大的定制能力,一切由你自己定
Noscript 提高瀏覽安全,可禁止一些惡意的腳本,可用效對(duì)付一些XSS跨站攻擊等
FoxyProxy 如果你需要時(shí)常在代理服務(wù)器上進(jìn)行切換的話(huà),這非常用幫助。如果結(jié)合像Tor之類(lèi)的工具,那么爬墻也不是件困難的事了。
py2exe是實(shí)用的python腳本工具,可以將python腳本程序轉(zhuǎn)換為exe執(zhí)行文件。這樣你的python程序就可以沒(méi)有安裝python運(yùn)行時(shí)環(huán)境的電腦里運(yùn)行了。py2exe方便地提取出python運(yùn)行時(shí)所需要的文件檔案,你需要做的就是寫(xiě)一個(gè)兩三行的安裝腳本文件。
py2exe可以從http://sourceforge.net/projects/py2exe/下載,唯一需要注意的是下載與你python版本號(hào)對(duì)應(yīng)的版本,簡(jiǎn)單的英文教程http://www.py2exe.org/index.cgi/Tutorial非常容易入門(mén)。
對(duì)早先寫(xiě)的一個(gè)代理驗(yàn)證腳本進(jìn)行exe文件封裝作為示例,這測(cè)試腳本名為HttpProxyTester.py。
首先,最好測(cè)試運(yùn)行一下待封裝的腳本以確定沒(méi)有問(wèn)題,然后在HttpProxyTester.py腳本的同級(jí)目錄新建一setup.py文件。
# setup.py
from distutils.core import setup
import py2exe
setup(console=['HttpProxyTester.py'])
上面的文件首先引入了distutils模塊,這模塊隨python安裝分發(fā)的,也就是說(shuō)內(nèi)置的。接著導(dǎo)入py3exe模塊,它其實(shí)對(duì)distutils做了一些功能擴(kuò)展。接下來(lái)的語(yǔ)句說(shuō)明是控制臺(tái)運(yùn)行。對(duì)于windows的GUI模式運(yùn)行,而不出控制臺(tái)窗口,則需要setup(windows=['xxx'])之類(lèi)指令,這對(duì)于pyWidget程序?qū)⒑苡杏谩?/p>
在完成安裝腳本后,接下來(lái)就是在控制臺(tái)下運(yùn)行這腳本。
>python setup.py py2exe
這時(shí)會(huì)打印出許多l(xiāng)og信息,并在同級(jí)目錄下出現(xiàn)兩個(gè)新的文件夾:build和dist。build文件夾下是py2exe生成的一些臨時(shí)文件,dist就是需要分發(fā)的文件內(nèi)容,可以這文件夾打包,然后在別的機(jī)子上運(yùn)行了。
總之,py2exe非常簡(jiǎn)單實(shí)用,三分鐘就可以搞定。
Python在處理功能復(fù)用和功能顆粒度劃分時(shí)采用了類(lèi)、模塊、包的結(jié)構(gòu)。這種處理跟C++中的類(lèi)和名字空間類(lèi)似,但更接近于Java所采用的概念。
類(lèi)
類(lèi)的概念在許多語(yǔ)言中出現(xiàn),很容易理解。它將數(shù)據(jù)和操作進(jìn)行封裝,以便將來(lái)的復(fù)用。
模塊
模塊,在Python可理解為對(duì)應(yīng)于一個(gè)文件。在創(chuàng)建了一個(gè)腳本文件后,定義了某些函數(shù)和變量。你在其他需要這些功能的文件中,導(dǎo)入這模塊,就可重用這些函數(shù)和變量。一般用module_name.fun_name,和module_name.var_name進(jìn)行使用。這樣的語(yǔ)義用法使模塊看起來(lái)很像類(lèi)或者名字空間,可將module_name 理解為名字限定符。模塊名就是文件名去掉.py后綴。下面演示了一個(gè)簡(jiǎn)單的例子:
#moduel1.py
def say(word):
print word
#caller.py
import module1
print __name__
print module1.__name__
module1.say('hello')
$ python caller.py
__main__
module1
hello
例子中演示了從文件中調(diào)用模塊的方法。這里還展示了一個(gè)有趣的模塊屬性__name__,它的值由Python解釋器設(shè)定。如果腳本文件是作為主程序調(diào)用,其值就設(shè)為_(kāi)_main__,如果是作為模塊被其他文件導(dǎo)入,它的值就是其文件名。這個(gè)屬性非常有用,常可用來(lái)進(jìn)行模塊內(nèi)置測(cè)試使用,你會(huì)經(jīng)常在一些地方看到類(lèi)似于下面的寫(xiě)法,這些語(yǔ)句只在作為主程序調(diào)用時(shí)才被執(zhí)行。
if __name__ == '__main__':
app = wxapp(0)
app.MainLoop()
模塊搜索路徑
上面的例子中,當(dāng)module1被導(dǎo)入后,python解釋器就在當(dāng)前目錄下尋找module1.py的文件,然后再?gòu)沫h(huán)境變量PYTHONPATH尋找,如果這環(huán)境變量沒(méi)有設(shè)定,也不要緊,解釋器還會(huì)在安裝預(yù)先設(shè)定的的一些目錄尋找。這就是在導(dǎo)入下面這些標(biāo)準(zhǔn)模塊,一切美好事情能發(fā)生的原因。
import os
import sys
import threading
...
這些搜索目錄可在運(yùn)行時(shí)動(dòng)態(tài)改變,比如將module1.py不放在當(dāng)前目錄,而放在一個(gè)冷僻的角落里。這里你就需要通過(guò)某種途徑,如sys.path,來(lái)告知Python了。sys.path返回的是模塊搜索列表,通過(guò)前后的輸出對(duì)比和代碼,應(yīng)能理悟到如何增加新路徑的方法了吧。非常簡(jiǎn)單,就是使用list的append()或insert()增加新的目錄。
#module2.py
import sys
import os
print sys.path
workpath = os.path.dirname(os.path.abspath(sys.argv[0]))
sys.path.insert(0, os.path.join(workpath, 'modules'))
print sys.path
$ python module2.py
['e:\\Project\\Python', 'C:\\WINDOWS\\system32\\python25.zip', ...]
['e:\\Project\\Python\\modules', 'e:\\Project\\Python', 'C:\\WINDOWS\\system32\\python25.zip', ...]
其他的要點(diǎn)
模塊能像包含函數(shù)定義一樣,可包含一些可執(zhí)行語(yǔ)句。這些可執(zhí)行語(yǔ)句通常用來(lái)進(jìn)行模塊的初始化工作。這些語(yǔ)句只在模塊第一次被導(dǎo)入時(shí)被執(zhí)行。這非常重要,有些人以為這些語(yǔ)句會(huì)多次導(dǎo)入多次執(zhí)行,其實(shí)不然。
模塊在被導(dǎo)入執(zhí)行時(shí),python解釋器為加快程序的啟動(dòng)速度,會(huì)在與模塊文件同一目錄下生成.pyc文件。我們知道python是解釋性的腳本語(yǔ)言,而.pyc是經(jīng)過(guò)編譯后的字節(jié)碼,這一工作會(huì)自動(dòng)完成,而無(wú)需程序員手動(dòng)執(zhí)行。
包
在創(chuàng)建許許多多模塊后,我們可能希望將某些功能相近的文件組織在同一文件夾下,這里就需要運(yùn)用包的概念了。包對(duì)應(yīng)于文件夾,使用包的方式跟模塊也類(lèi)似,唯一需要注意的是,當(dāng)文件夾當(dāng)作包使用時(shí),文件夾需要包含__init__.py文件,主要是為了避免將文件夾名當(dāng)作普通的字符串。__init__.py的內(nèi)容可以為空,一般用來(lái)進(jìn)行包的某些初始化工作或者設(shè)置__all__值,__all__是在from package-name import *這語(yǔ)句使用的,全部導(dǎo)出定義過(guò)的模塊。
應(yīng)用程序國(guó)際化,在開(kāi)源世界里常以i18n被提及,i18n是Internationalization的簡(jiǎn)寫(xiě),正好18個(gè)字母。在wxPython程序進(jìn)行i18n,如果字符串是編碼在源文件中時(shí),完全可按照python程序的i18n的方法,即使用gexttext和locale模塊。而wxPython程序在使用XRC文件做為界面資源時(shí),則應(yīng)使用wx.Locale模塊,它封裝了區(qū)域化相關(guān)的操作。i18n,或者國(guó)際化實(shí)際上涉及到語(yǔ)言習(xí)慣,數(shù)字格式等等類(lèi)別的內(nèi)容。這里只介紹語(yǔ)言多國(guó)化,將一個(gè)簡(jiǎn)單的英文程序轉(zhuǎn)換為中文,涉及到源文件,可從這里下載。
創(chuàng)建PO文件
PO文件是Portable Object文件的簡(jiǎn)稱(chēng),它包含需要翻譯的字符串。我們需要從源文件進(jìn)行提取。首先,對(duì)源文件test.py編輯,標(biāo)識(shí)代碼里需要翻譯的字符串內(nèi)容。我們使用_("xx")的方法,這種形式可能在許多開(kāi)源源代碼中見(jiàn)識(shí)過(guò)。
#加載菜單欄
menubar = rc.LoadMenuBar('IDR_MENU')
這里的IDR_MENU是資源標(biāo)識(shí)ID,不需要翻譯,因此不做改變,而下面的代碼:
info.SetVersion('1.0')
info.SetDescription('XRC i18n Demo')
'XRC i18n Demo'是描述性的文本,需要進(jìn)行翻譯,將需要處理為
info.SetVersion('1.0')
info.SetDescription(_('XRC i18n Demo'))
接著需要生成.pot(Portable Object Template),這是po的模板文件。在將來(lái)程序可能配置成其他語(yǔ)種,其他語(yǔ)言的po文件都從它而來(lái)。為了創(chuàng)建這文件,需要用到GNU gettext工具集中的xgettext。向xgettext傳入些必要的信息,來(lái)創(chuàng)建.pot文件。
>xgetttext --output=test.pot test.py
我們將wxPython界面以XRC文件保存了,那里同樣有要翻譯的字符串需要提取。用XRCed工具將XRC生成python代碼,勾選上'Generate gettext strings'項(xiàng)即可。將源文件和XRC生成的test_xrc.py文件一起處理,生成一個(gè)test.pot。
>xgettext --output=test.pot test.py test_xrc.py
將得到的test.pot另存為test.po文件,然后進(jìn)行翻譯編輯,在這過(guò)程中文件需要使用utf-8編碼。將對(duì)應(yīng)的英文翻譯成中文,將charset更改為utf-8。
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: test.py:19
msgid "XRC i18n Demo"
msgstr "XRC 國(guó)際化示例"
...
.pot和.po這些文件都是文本文件,主要供翻譯者使用。為了使程序在運(yùn)行時(shí)能獲取相關(guān)的翻譯的內(nèi)容,要進(jìn)行所謂的編譯過(guò)程,將文本文件轉(zhuǎn)換為二進(jìn)制文件.mo。這里用了gettext工具集中的另一程序msgfmt。
> msgfmt --output=test.mo test.po
因?yàn)閣indows下沒(méi)有像linux像有公共存儲(chǔ).mo文件的目錄,保持平臺(tái)的遷移性,在應(yīng)用程序本地目錄下新建locale目錄,用來(lái)存放編譯過(guò)的.mo文件,然后將test.mo移動(dòng)至locale目錄。在完成這些步驟后,就轉(zhuǎn)入代碼方面的更改了。
wxPython代碼更改
原先的代碼只需要做小改動(dòng):
def OnInit(self):
wx.Locale.AddCatalogLookupPathPrefix('locale')
self.locale = wx.Locale(wx.LANGUAGE_CHINESE_SIMPLIFIED)
self.locale.AddCatalog('test')
import __builtin__
__builtin__.__dict__['_'] = wx.GetTranslation
首先,增加了新的目錄文件路徑,這將使wxPython搜索這個(gè)目錄,尋找匹配的.mo文件。接著創(chuàng)建wx.Locale對(duì)象,將其初始化為簡(jiǎn)體中文,這將對(duì)應(yīng)于zh_CN。最后將wx.GetTranslation做了一全局映射,這樣你在其他類(lèi)中,比如示例中TestFrame也能使用_('xx')調(diào)用。這樣wxPython的i18n工作就完成了,下面是翻譯前后的界面截圖。
一些有益的討論
.mo文件的查找目錄
如果你將locale目錄下的test.mo文件刪除掉,然后將test.py中的wx.LANGUAGE_CHINESE_SIMPLIFIED改為wx.LANGUAGE_CHINESE,重新運(yùn)行程序看看。發(fā)現(xiàn)界面變成了如下的繁體中文,但是菜單'檔案'下的Exit還是英文。
因?yàn)槿笔?mo文件,但又指定wx.LANGUAGE_CHINESE,wxPython運(yùn)行時(shí)使用了wxstd.mo文件。wxstd.mo有許多預(yù)編譯好的常見(jiàn)字符串的對(duì)應(yīng)關(guān)系,它隨wxPython發(fā)布,在wx/locale下有許多語(yǔ)言版本的wxstd.mo。
對(duì)于wxPython會(huì)對(duì)待查目錄"DIR"來(lái)搜索.mo文件,查找它下面的這些目錄,(DIR/LANG/LC_MESSAGES;DIR/LANG;DIR),對(duì)于哪些是待查目錄,各個(gè)系統(tǒng)下又有不同,在所有的平臺(tái)上,LC_PATH環(huán)境變量指定的目錄將成為待查目錄,在Linux下/share/locale, /usr/share/locale, /usr/lib/locale, /usr/locale /share/locale以及當(dāng)前目錄將是待查目錄。在上面我們已經(jīng)用過(guò)AddCatalogLookupPathPrefix()函數(shù),其作用就是增加自己的待查目錄。
在示例程序中,將test.mo放在locale\zh_CN\LC_MESSAGES或者locale\zh\LC_MESSAGES同樣是可行的。但是如果使用wx.LANGUAGE_CHINESE指定,則zh_CN目錄將不可行,因?yàn)樗皇翘鼗夸洠负?jiǎn)體中文,而zh目錄同樣適用。
工具鏈再討論
gettext進(jìn)行國(guó)際化是開(kāi)源社區(qū)的主流方案,它也提供了許多實(shí)用工具供使用。上面提到了xgettext,msgfmt,還有msginit.exe,它將根據(jù).pot文件創(chuàng)建新的.po文件,然后初始化一些元信息,像作者信息,項(xiàng)目,以及編碼等,當(dāng)然也可像上面的手工編輯。msgmerge.exe將兩個(gè).po文件進(jìn)行合并。除了使用GNU Gettext工具集,也可使用隨python發(fā)布的tool\i18n目錄下pygettext.py和msgfmt.py,它們等同于上述的兩個(gè)工具。
對(duì)于編輯.po文件,可以嘗試一下Poedit,它提供了圖形化的編輯環(huán)境,其他功能我就不清楚了。
在Windows下,許多網(wǎng)絡(luò)程序的連接依賴(lài)于IE瀏覽器中的代理服務(wù)器的設(shè)置,IE瀏覽器的代理設(shè)置很可能設(shè)定了注冊(cè)表中的全局網(wǎng)絡(luò)連接配置。
我在IE瀏覽器中設(shè)置了代理,而使用Maxthon瀏覽網(wǎng)頁(yè)。在寫(xiě)Python時(shí),用了urllib2庫(kù),后來(lái)出現(xiàn)了下面的錯(cuò)誤:
urllib2.URLError: <urlopen error (10061, 'Connection refused')>
先前這個(gè)程序是運(yùn)行正確的,又直接用瀏覽器訪(fǎng)問(wèn)需要的網(wǎng)址,正常。通過(guò)排查,發(fā)現(xiàn)IE瀏覽器中設(shè)置了代理,而代理無(wú)效,而urllib2庫(kù)使用其網(wǎng)絡(luò)配置,因此無(wú)法連接。通過(guò)取消代理,程序連接正常。
還有一例是,剛才用Windows Live Writer檢索日志,和發(fā)布日志時(shí)出錯(cuò),分別顯示如下的錯(cuò)誤:
?
這也是因?yàn)閃LW使用IE的網(wǎng)絡(luò)設(shè)置,造成的網(wǎng)絡(luò)錯(cuò)誤而顯示的錯(cuò)誤提示。
因此在設(shè)置了IE代理,并使用其他與網(wǎng)絡(luò)相關(guān)的程序,要特別注意其是否對(duì)IE代理設(shè)置有依賴(lài)。像Maxthon等就可選擇不使用IE代理配置的選項(xiàng)。
Windows Live Writer是寫(xiě)博客的利器,非常好用。只是對(duì)一些常見(jiàn)的html標(biāo)簽支持不足,比如沒(méi)有預(yù)排文本標(biāo)簽<pre>之類(lèi)的。在插入示例代碼時(shí),我不喜歡使用網(wǎng)上的那些高亮插件,它們?cè)黾恿艘恍┪腋杏X(jué)不友好的標(biāo)簽元素。我在寫(xiě)文章時(shí),代碼放在<pre>標(biāo)簽,然后使用自定義的code類(lèi),如果是一些屏幕輸入輸入文本,會(huì)用一個(gè)console類(lèi)來(lái)進(jìn)行說(shuō)明。如果直接從源代碼拷貝文本至html源文件時(shí),xml文件的的<>"之類(lèi)標(biāo)簽需要進(jìn)行轉(zhuǎn)義才可以。在這之前,我都需要手工將WLW切換到HTML模式進(jìn)行創(chuàng)作,然后修改這些標(biāo)簽,非常麻煩。這樣干了幾次后,昨天決定自己寫(xiě)個(gè)WLW插件用。在搜索引擎的幫助下,找到Dflying Chen的 為Windows Live Writer開(kāi)發(fā)插件——InsertSearchPageLink這篇文章,并在其參照完成了插件編寫(xiě)。
但在找到這篇文章之前,和編寫(xiě)插件的過(guò)程中,還是費(fèi)了很多功夫。最早我認(rèn)為寫(xiě)插件是需要下載SDK之類(lèi)的軟件,所以在Live Writer官方開(kāi)發(fā)網(wǎng)站,Live Writer網(wǎng),MSDN之類(lèi)的找了個(gè)遍,看見(jiàn)是有SDK之類(lèi)字樣的下載,但弄不下來(lái)只有文檔,根本不見(jiàn)其什么頭文件,DLL之類(lèi)的。在這花費(fèi)了很多時(shí)間,最后才發(fā)現(xiàn)WLW插件的SDK是隨WLW一起分發(fā)了,也就是WindowsLive.Writer.Api.dll之類(lèi)的,這些dll 都隨WLW主程序在一個(gè)目錄中。還有一點(diǎn)是,現(xiàn)在WLW在中國(guó)是隨Live套件一起發(fā)布的,因此路徑由原來(lái)的C:\Program Files\Windows Live Writer變成了C:\Program Files\Windows Live\Writer,插件目錄為Plugin。如果在網(wǎng)上發(fā)現(xiàn)有好用的插件,只需要將其發(fā)布的插件dll扔到這個(gè)目錄就行了。
在開(kāi)發(fā)中碰到圖標(biāo)資源不能成功加載,在Dflying Chen的文章中特意提到了圖標(biāo)資源需要是嵌入形式,我也按照其操作的,總以為是這里出現(xiàn)問(wèn)題。后來(lái)花了一些時(shí)間,才找到總是的根源:自己在開(kāi)發(fā)中更改了工程名,導(dǎo)致最后生成的程序集的名稱(chēng)與后來(lái)的命名空間名稱(chēng)不一致,圖標(biāo)路徑就出錯(cuò)了。C#也只是這次用一下,這些都沒(méi)有接觸到。
昨天弄完自己的“插入Pre標(biāo)記”插件后,想到自己寫(xiě)博客常需要截圖,遂想再開(kāi)發(fā)一個(gè)截圖工具的。最早搜到了別人調(diào)用SnagIt搜件,不好用,因?yàn)镾nagIt是商業(yè)軟件,需要注冊(cè)的。后來(lái)找到了picpick,小巧免費(fèi),非常實(shí)用。我想調(diào)用picpick的,但是在參照Insert SnagIt Screen Capture發(fā)現(xiàn)是用COM接口,而無(wú)奈picpick沒(méi)有這樣供開(kāi)發(fā)使用的接口考慮,最終不可行。后來(lái)經(jīng)過(guò)一些其他的嘗試,都告失敗。最后還是搜索幫了忙,找到了Screen Capture這個(gè)插件,原來(lái)有別人已完工了。
最后附上,我用這個(gè)新插件截的圖,非常好用,只需一步:
安裝Cygwin
在cgywin官方主頁(yè)下載安裝文件setup.exe,這只是一個(gè)網(wǎng)絡(luò)安裝包,體積很小。cgywin包含了許多GNU下的應(yīng)用程序,真正安裝時(shí)會(huì)根據(jù)你選擇的組件,會(huì)自動(dòng)去網(wǎng)上下載安裝的。在國(guó)內(nèi)最好使用鏡像服務(wù),這樣速度會(huì)提高很多,建議去http://www.cygwin.net.cn/或http://www.cygwin.cn/下載上述的安裝包,并在安裝進(jìn)行到Choose A Download Site這個(gè)步驟時(shí),選擇合理的鏡像。由于中國(guó)南北網(wǎng)速的差異,上述兩個(gè)地址都嘗試一下,看看哪個(gè)對(duì)你而言速度更快一些。
在進(jìn)行到Select Packages這個(gè)步驟時(shí),選擇你需要包,建議如下:
- Shells -> rxvt-unicode-x? 強(qiáng)大的X終端,可用它替換windows下的cmd.exe
- Net-> openssh? ssh客戶(hù)端,可作putty的替換
- Net-> inetutils? 可選,包含一些基本的網(wǎng)絡(luò)工具,如telnet,否則在cygwin下無(wú)法使用windows的telnet
cygwin安裝時(shí)會(huì)自動(dòng)進(jìn)行包關(guān)聯(lián),在安裝rxvt時(shí),已自動(dòng)將X server安裝上了。
配置調(diào)整
啟動(dòng)cygwin,實(shí)際上是運(yùn)行cgywin.bat批處理,它又調(diào)用了cmd.exe。我們將安裝的rxvt作為默認(rèn)終端,需要修改cygwin.bat。下面是我機(jī)子上的配置修改,請(qǐng)對(duì)應(yīng)修改相應(yīng)的路徑。
@echo off
d:
chdir d:\Cygwin\bin
rxvt -e bash --login -i
調(diào)整rxvt觀(guān)感,需要修改你用戶(hù)主目錄下的.Xdefaults文件,此文件在你選擇的安裝目錄下的home\usrname下,在我的機(jī)子上是D:\Cgywin\home\len。若不存在,可在此目錄下新建一個(gè),修改內(nèi)容如下:
Rxvt*background: black
Rxvt*foreground: #E2E6C7
Rxvt*font: 9x16
Rxvt*boldFont: 9x16
Rxvt*scrollBar_right: True
Rxvt*saveLines: 1024
Rxvt*geometry: 80x30
Rxvt*color0: black
Rxvt*color1: red
Rxvt*color2: green
Rxvt*color3: yellow
Rxvt*color4: blue
Rxvt*color5: magenta
Rxvt*color6: cyan
Rxvt*color7: white
Rxvt*color8: burlywood1
Rxvt*color9: sienna1
Rxvt*color10: PaleVioletRed1
Rxvt*color11: LightSkyBlue
Rxvt*color12: white
Rxvt*color13: white
Rxvt*color14: white
Rxvt*color15: white
在cygwin下也是可以訪(fǎng)問(wèn)Windows下其他盤(pán)符的,如cd /cygdrive/c/windows,就轉(zhuǎn)到了C盤(pán)windows目錄下。這樣對(duì)于在linux下工作的人說(shuō)有點(diǎn)兒別扭,更希望是以cd /mnt/c/windows的mount方式來(lái)訪(fǎng)問(wèn)其他盤(pán)符。這需要修改注冊(cè)表的選項(xiàng),將HKLM\software\Cygnus Solutions\Cgywin\mounts v2下的子項(xiàng)cygdrive prefix更改為/mnt即可。
遠(yuǎn)程登陸Linux桌面
其實(shí)這里介紹的不僅僅適用于Linux,而是針對(duì)X Window的。X Widonw的介紹不進(jìn)行贅述,但需要明確其中的服務(wù)器端和客戶(hù)端的區(qū)別,在X Window的概念中服務(wù)器端是指你進(jìn)行顯示,輸入輸出的機(jī)器,也是接下來(lái)示例中的本機(jī)len-computer,IP為10.3.164.70,而客戶(hù)端指的是進(jìn)行遠(yuǎn)程登陸的機(jī)器auto-desktop,IP為10.3.164.74。
在局域網(wǎng)內(nèi)最簡(jiǎn)單的方法是使用XDMCP連接,這時(shí)遠(yuǎn)程的機(jī)器啟用xdmcp。那臺(tái)機(jī)器運(yùn)行著ubuntu-8.04,用gdm進(jìn)行窗口管理,編輯/etc/gdm/gdm.conf-custom如下,其他版本的linux需找到對(duì)應(yīng)的窗口管理的配置文件。
[security]
DisallowTCP=false
[xdmcp]
Enale=true
修改完后,在遠(yuǎn)程機(jī)器上重啟服務(wù),$sudo /etc/init.d/gdm restart。接下來(lái)本機(jī)啟動(dòng)cgywin,轉(zhuǎn)到X目錄下,運(yùn)行Xwin.exe,使用 -query指定遠(yuǎn)程的linux機(jī)器的ip即可。
Len@len-computer /usr/X11R6/bin
$ cd /usr/X11R6/bin
Len@len-computer /usr/X11R6/bin
$ Xwin -query 10.3.164.74
這里會(huì)出現(xiàn)如下面圖示的窗口,提示輸入用戶(hù)名和密碼。另再附一張?jiān)诘顷懗晒螅以诒镜貓?zhí)行遠(yuǎn)程操作的截圖。
如果你需要連接的遠(yuǎn)程機(jī)器比較固定,可以修改本地機(jī)器d:\cgygin\usrX11R6\bin\startxdmcp.bat中的REMOTE_HOST值為你需要連接機(jī)器的IP,這個(gè)批處理設(shè)置了一些有用的環(huán)境變量值。或許你需要?jiǎng)?chuàng)建一個(gè)桌面的快鍵方式,這樣每次點(diǎn)擊,就直接連接到遠(yuǎn)程機(jī)器了。
不引入桌面環(huán)境
可能有時(shí)候只需要將某個(gè)需要X服務(wù)的遠(yuǎn)程應(yīng)用程序引入到本地桌面顯示,而不需要啟動(dòng)像上面的GNOME或者KDE等龐大的桌面環(huán)境。這樣做比較適合喜歡終端操作的人,我就常常終端敲命令,然后將gvim,openoffice這些從遠(yuǎn)程導(dǎo)入到本地操作。
找到d:\cgywin\usr\X11R6\bin\startwin.bat,將%RUN% xterm -e /usr/bin/bash -l注釋掉,因?yàn)槲覀兗航?jīng)有了rxvt,不需要一個(gè)新的xterm終端了,執(zhí)行該批處理文件,就會(huì)在本機(jī)運(yùn)行X server。啟動(dòng)cgywin,用ssh登陸到遠(yuǎn)程機(jī)器上,執(zhí)行如下命令,導(dǎo)出DISPLAY環(huán)境變量和運(yùn)行你感興趣的程序。
auto@Auto-desktop:~$ export DISPLAY=10.3.164.70:0.0
auto@Auto-desktop:~$ gvim&
[1] 22652
auto@Auto-desktop:~$ oowriter&
其中環(huán)境變量DISPLAY中的:0.0部分表示X server的display和screen。display指運(yùn)行著X server實(shí)例。如果使用TCP/IP連接,表示的是端口6000+display號(hào)做為連接。screen代表X server上的不同輸出設(shè)備。我在例子中執(zhí)行g(shù)vim和openoffice.org-writer,運(yùn)行的效果可看下面的截圖。在ubuntu上運(yùn)行著的gvim和openoffice都在我本機(jī)10.3.164.70上顯示了,并且可操作。
有用的鏈接
Cgywin/X FAQ 在碰到一些操作問(wèn)題時(shí),不妨先看看這份FAQ
使用cygwin X server實(shí)現(xiàn)Linux遠(yuǎn)程桌面 easwy介紹了KDE環(huán)境下的配置,部分受此啟發(fā)
使用rxvt做為cygwin終端 碰到rxvt中文顯示問(wèn)題時(shí),或許有幫助