2008年12月29日 星期一

Python 的時間

因為經常為 Python 處理時間的問題煩惱,所以打算留篇記錄以便之後查閱。

  • 取得今天日期


    import datetime
    today = datetime.date.today()
    # today 是一個 datetime.date object

  • 取得現在日期及時間


    import datetime
    current = datetime.datetime.now()
    # current 是一個 datetime.datetime object

  • 建立日期


    import datetime
    some_day = datetime.datetime(2008, 12, 25)

  • 建立日期及時間


    import datetime
    some_day = datetime.datetime(2008, 12, 25, 12, 0, 0)

  • 格式化現在時間


    from time import strftime
    now = strftime('%Y-%m-%d %H:%M:%S')
    # now 是一個 str, '2008-12-29 16:12:34'

  • 格式化 datetime.datetime object


    import datetime
    some_day = datetime.datetime(2008, 12, 25)
    print some_day.strftime('%Y-%m-%d')
    # 得到 '2008-12-25'

  • datetime.datetime 可以相減(算差距),也可以直接比較

  • 換成 tuple


    import datetime
    now_tuple = datetime.datetime.now().timetuple()
    # now_tuple 會得到一個 tuple

  • 取得 timestamp


    import time
    ts = time.time()
    # ts 是一個 timestamp, type 為 float

  • 從 timestamp 換回 datetime object


    import time
    import datetime
    ts = time.time()
    dt = datetime.datetime.fromtimestamp(ts)

  • 從 time tuple 換成 timestamp


    from time import mktime
    ts = mktime(now_tuple)
    # ts 是 timestamp

2008年10月12日 星期日

驗證檔案的內容

我們在很多網站下載檔案時,為了確保檔案內容沒有被修改過,通常檔案的提供者會提供你一組 MD5 或 SHA-1 之類的字串供你驗證,我把這個動作寫成一個 python script 來快速檢查:


#!/usr/bin/env python
# -*- coding: utf-8 -*-
import hashlib
import os
import sys

def usage(app_name):
"""
The usage doc
"""
return """Usage: %s _filename_ _hash_algo_ _hash_value_"""

def main(args):
"""
Main program
"""
try:
f = open(args[0], 'r')
dig = getattr(hashlib, args[1])(f.read()).hexdigest()
f.close()
print (dig == args[2] and 'Valid') or 'Invalid'
except IOError, e:
print '找不到檔案 "%s"' % args[0]
except AttributeError, e:
print 'Hash 演算法名稱錯誤'

def commandline():
if len(sys.argv) > 2:
main(sys.argv[1:])
else:
print usage(sys.argv[0])

if __name__ == '__main__':
commandline()

簡單的使用方法就是 「script 檔名 演算法 驗證碼」,如果我將這個 script 存成一個叫 verify.py 的檔案,下載了一個 foo.dat 的檔案,要用 sha1 演算法檢查 abcdefg(假的,sha-1 的碼很長),那就這樣用:

verify.py foo.dat sha1 abcdefg

演算法直接用 python hashlib 裡支援的,如果不支援就會直接跳到 AttributeError :P

2008年9月3日 星期三

根據 ID 抓取 YouTube 影片


def progress_hook(block_number, block_size, total_size):
if total_size > 0:
percentage = 100 * block_number * block_size / total_size
if percentage > 100:
percentage = 100
print '%2d%%' % percentage

def getYouTubeVideoByID(video_id, output_filename):
import re, urllib
url = 'http://www.youtube.com/v/%s' % (video_id)
real_url = urllib.urlopen(url).geturl()
match = re.findall("t=([^&]*)", real_url)
if match:
fetch_url = 'http://www.youtube.com/get_video.php?video_id=%s&t=%s' % (video_id, match[0])
print fetch_url
try:
urllib.urlretrieve(fetch_url, output_filename, progress_hook)
except urllib.ContentTooShortError:
print 'ContentTooShortError'


其中 progress_hook 是用來顯示進度的,如果不喜歡可以自己修改格式,或是在 getYouTubeVideoByID 裡面呼叫 urllib.urlretrieve 的地方把 progress_hook 這個參數拿掉。

使用方法: getYouTubeVideoByID(<id>, <file_name>)
範例:
getYouTubeVideoByID('2scOjA_U09w', 'E:\\CCF.flv')

2008年6月18日 星期三

動態改變 instance 的 member function

首先先建立一個 class:


class foo:
def say(self, s):
print 'Hello, %s' % (s)

f = foo()
f.say('Bob')

這樣會印出 'Hello, Bob'。
如果想把裡面的 say 換成自己定義的 function,可以先定義該 function:

def helloworld(self, s):
print 'Hello World %s' % (s)

然後再用 new.instancemethod 把它給換掉:

import new
f.say = new.instancemethod(helloworld, f, foo)
f.say('Alice')

這樣就會印出 'Hello Wolrd, Alice' 囉

2008年4月29日 星期二

Python 的字元編碼

Python 並不像其它語言一樣,看你的程式碼檔案是什麼字元編碼就用什麼編碼來解讀內部的字串。所以必須在檔案開頭處清楚地宣告
# -*- coding: utf-8 -*-
當然你的程式碼檔案也要存成對應的編碼才能正常執行。

而如果在一個 utf-8 編碼的程式碼裡,若要將某 utf-8 字串轉成 cp950 (在 Windows 上蠻常用的)的話,只要:

str = "我是UTF-8的字串"
print str.decode('utf-8').encode('cp950')

就可以了。相當方便!

Python 版的 switch case

其實一直不太清楚為什麼 Python 內建的語法會沒有 switch/case 的用法,所以這時候只好自己做一下了

如果本來在 C 裡會寫這樣:

x = 0;
switch (value) {
case 1:
x += 1;
break;
case 2:
x *= 5;
break;
...
}

那在 Python 裡可以寫成這樣:
x  = 0
{
1: lambda y: y += 1,
2: lambda y: y *= 5
...
}[value](x)


簡單地說就是用 dictionary 來作。

2008年4月24日 星期四

簡易密碼產生器