andelf fledna Feather

显示标签为“python”的博文。显示所有博文
显示标签为“python”的博文。显示所有博文

2011年3月25日星期五

uc_authcode 函数的 Python 实现.

很多其他语言开发的网站程序需要整合到UCenter中,但是由于 UCenter 是使用
PHP开发的,很难移植。其中最难缠的 uc_authcode.
测试实现了 uc_authcode 函数。纯 python,无三方库。

Creative Commons License
This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#  FileName    : uc_authcode.py 
#  Author      : Feather.et.ELF  
#  Created     : Fri Mar 25 00:11:57 2011 by Feather.et.ELF 
#  Copyright   : Feather Workshop (c) 2011 
#  Description : uc_authcode in python 
#  Time-stamp: <2011-03-25 00:12:13 andelf> 


def uc_authcode(string, op='DECODE', key='', expiry=0):
    import time as t
    import base64
    import hashlib

    md5 = lambda s: hashlib.md5(s).hexdigest()
    microtime = lambda : str(t.time())
    time = lambda : int(t.time())

    ckey_length = 4

    key = md5(key) # or use key = md5(key or UC_KEY)
    keya = md5(key[:16])
    keyb = md5(key[16:])
    if op == 'DECODE':
        keyc = string[:ckey_length]
    else:
        keyc = md5(microtime())[-ckey_length:]

    cryptkey = keya + md5(keya + keyc)
    key_length = len(cryptkey)

    if op == 'DECODE':
        string = base64.b64decode(string[ckey_length:])
    else:
        string = ('%010d' % (expiry + time() if expiry else 0)) + \
                 md5(string + keyb)[:16] + string

    string_length = len(string)
    result = ''

    box = range(256)

    rndkey = [ord(cryptkey[i % key_length]) for i in xrange(256)]
    
    j = 0
    for i in xrange(256):
        j = (j + box[i] + rndkey[i]) % 256
        box[i], box[j] = box[j], box[i]

    a = j = 0
    for i in xrange(string_length):
        a = (a + 1) % 256
        j = (j + box[a]) % 256
        box[a], box[j] = box[j], box[a]
        result += chr(ord(string[i]) ^ (box[(box[a] + box[j]) % 256]))

    if op == 'DECODE':
        try:
            # use assert to catch misc case
            assert (int(result[:10])== 0) or (int(result[:10]) - time()> 0)
            if result[10:26] == md5(result[26:] + keyb)[:16]:
                return result[26:]
            else:
                return ''
        except:
            return ''
    else:
        return keyc + base64.b64encode(result).replace('=', '')

def test():
    APP_KEY = 'x2ta5X12oTz75gbRTMB6gY6thZ7D83'
    text = 'this_is_the_string_to_be_encrypted'
    print 'text=', text
    e = uc_authcode(text, "ENCODE", APP_KEY)
    print 'e=', e
    e += '='*(len(e) % 4)               # must fix padding
    assert uc_authcode(e, "DECODE", APP_KEY) == text
    
    print 'rslt=', uc_authcode(e, "DECODE", APP_KEY)


if __name__ == '__main__':
    test()

2010年4月17日星期六

[IronPython]WPF应用的 STAThread 属性处理

最近用铁蟒写 WPF 应用, 遇到纠结的问题. (使用 tools/pyc.py 编译时会遇到, 解释执行正常) 任何一个 WPF 程序,Main 的前面都必须有 [STAThread] 属性, 否则会有运行时错误: Unhandled Exception: System.InvalidOperationException: The calling thread must be STA, because many UI components require this. 找了下相关资料 发现有 http://www.ironpython.info/index.php/Setting_the_Clipboard 整了个还算 Pythonic 的方法, 这里和大家分享下 from System.Threading import Thread, ParameterizedThreadStart, \ ApartmentState, ThreadStart def STAThread(main): def new_main(*args, **kwargs): t = Thread(ParameterizedThreadStart(main)) t.ApartmentState = ApartmentState.STA t.Start(*args, **kwargs) return new_main 这样, 可以直接使用 @STAThread 修饰主函数. 由于使用了 ParameterizedThreadStart, 主函数必须接受参数. 然后想到了版本2 def STAThread(main): if main.__code__.co_argcount: # if main accept params def new_main(*args, **kwargs): t = Thread(ParameterizedThreadStart(main)) t.ApartmentState = ApartmentState.STA t.Start(*args, **kwargs) else: def new_main(): t = Thread(ThreadStart(main)) t.ApartmentState = ApartmentState.STA t.Start() return new_main 需要注意的是, 如果主函数写在 class 里,那么 @STAThread 必须在 @staticmethod 之后, 原因..(如果你知道 @ 是什么意思的话). 或许有其他更好的方法, 欢迎讨论 :)

2009年6月21日星期日

ZMI中对象简单介绍

ZMI中对象简单介绍
对象名说明
portal_porperties站点属性设置。site_properties:站点属性,navtree_properties:导航属性
portal_action站点操作项
portal_controlpanel站点控制面板操作项
portal_actionicons站点操作项图标
portal_type内容类型管理
portal_factory内容创建控制
content_type_registry内容和文件映射
portaL_registry用户注册
portal_membership用户管理
acl_users用户源
portal_memberdata用户属性
portal_skin站点皮肤管理
portal_setup站点设置管理
portal_catalog索引维护
portal_migration站点升级
portal_atctATcontentType升级
mimetype_registry文件类型注册表
portal_transform内容转换
portal_discussion站点评注引擎
portal_quickinstaller安装和卸载产品
error_log错误日志
MailHost邮件设置

2009年4月23日星期四

Guido hates tail recursion elimination

大叔对尾递归还是有点意见的....或许大叔对 FP 不感冒. 其实对于某某某无比吹捧 FP 还是很反感的, 或许搞技术的大都凌驾吧. 不过侧面能说明一些问题, 如果 python 支持尾递归优化, 那么.... 其实 python 对 lambda 等的支持很有限. 大叔说: 简言之, 为什么 Python 不用呢, 因为不 Pythonic. 具体就是: TRE is incompatible with nice stack traces. Python 不会让程序员写基于 TRE 特性的代码.
Once tail recursion elimination exists, developers will start writing code that dependson it, and their code won't run on implementations that don't provide it: a typical Python implementation allows 1000 recursions, which is plenty for non-recursively written code and for code that recurses to traverse, for example, a typical parse tree, but not enough for a recursively written loop over a large list.
还有更牛的理由
I don't believe in recursion as the basis of all programming. 
; 这个我也想对某些迷信 FP 的人说. 
最后, 它提到了一些 Python 中如果使用 TRE 的后果, 如果实现 TRE, 那么将有更多的问题需要解决. 所以, 既然不是 FP, 就没必要整那么多 FP 的东西. lambda, 方便而已, 不是让你整 FP 的.
欢迎拜见大叔:

2009年4月12日星期日

python 中 lambda 的倒掉

灵感来自: http://math.andrej.com/2009/04/09/pythons-lambda-is-broken/ 长话短说, 先看代码.
>>> fs = [(lambda n: i + n) for i in range(10)]
>>> fs[3](4)
13
不觉得该是 3 + 4 = 7 么?
>>> [f(4) for f in fs]
[13, 13, 13, 13, 13, 13, 13, 13, 13, 13]
.....撞石头上了... 换 def 看:
>>> fs = []
>>> for i in range(10):
...    def f(n): return i+n
...    fs.append(f)
...
>>> [f(4) for f in fs]
[13, 13, 13, 13, 13, 13, 13, 13, 13, 13]
其实这时候已经有点眉目了, 继续看下去:
>>> fs = []
>>> for i in range(10):
...    def f(n, i=i): return i+n
...    fs.append(f)
...
>>> [f(4) for f in fs]
[4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
作者提到 Haskell 是没问题的:
Prelude> let fs = [(\n -> i + n) | i <- [0..9]] 
Prelude> [f(4) | f <- fs] 
[4,5,6,7,8,9,10,11,12,13]
想也是~ Haskell 就是做这个的. 怎么回事呢? 我觉得是 lexical scope(static scope) 和 dynamic scope 的关系. lisp 中一般都会讲到这个. 在 def 使用时就已经可以看出, i 在这里作为全局变量了(或者说是上一级变量), 而调用的时候使用的是当前全局环境中的 i. 而 def f(n, i=i) 中, 局部 i 覆盖了全局的 i, 那么也就是说, def 参数列表中默认值参数在定义后就已经绑定.

2009年4月11日星期六

python 的 yield

以前只是类似生成器表达式那样使用... 其实有N多牛B用法. 真长见识~! http://www.dabeaz.com/coroutines/index.html 例如:
# grep.py
#
# A very simple coroutine

def grep(pattern):
  print "Looking for %s" % pattern
  while True:
    line = (yield)
    if pattern in line:
         print line,
# Example use
if __name__ == '__main__':
  g = grep("python")
  g.next()
  g.send("Yeah, but no, but yeah, but no")
  g.send("A series of tubes")
  g.send("python generators rock!")
对于生成器函数来说, 有 next() ,send(), throw() 方法.
  • next() 比较容易理解.
  • send(arg) 向生成器发送参数, 会被 line = (yield) 捕获.
  • throw(typ[,val[,tb]]) -> raise exception in generator, return next yielded value or raise StopIteration. 参数分别是, 异常类型, 异常 str, traceback object.
这算是最简单的.... 配合函数修饰符, 相当强大.... yield ...

2009年4月5日星期日

字符计数

Smalltalk(8063446)  8:58:35 
>>> from collections import Counter 
>>> c=Counter() 
>>> for letter in 'here is a sample of english text':
...   c[letter] += 1 
... 
>>> c
Counter({' ': 6, 'e': 5, 's': 3, 'a': 2, 'i': 2, 'h': 2, 'l': 2, 't': 2, 'g': 1, 'f': 1, 'm': 1, 'o': 1, 'n': 1, 'p': 1, 'r': 1, 'x': 1}) >>> c['e'] 5 >>> c['z'] 0 
;; 其实是个 reduce 过程.  
Feather(85660100)  11:45:28 
>>> reduce(lambda d,s: dict(d, **{s:d.get(s,0)+1}), \
            'here is a sample of english text', {}) 
{'a': 2, ' ': 6, 'e': 5, 'g': 1, 'f': 1, 'i': 2, 'h': 2, 'm': 1, 'l': 2, 'o': 1, 'n': 1, 'p': 1, 's': 3, 'r': 1, 't': 2, 'x': 1} 
其实要说的是.... dict() 很强大很强大. 以及其他 python type 函数.

2009年2月28日星期六

百度谷歌造[有图有真相][baidu made from google]

有图有真相... 上图:
真相:
#!win32 only. no unix magic chars
# coding=utf-8

# need pywin32 module
import win32com.client

bro = win32com.client.Dispatch("InternetExplorer.Application")
# show window
bro.Visible = True
bro.Navigate("http://www.baidu.com")

while bro.Busy:
    pass

print bro.LocationName
# MSDN: bro.Document is a DOM object
doc = bro.Document
logo = doc.getElementsByTagName('img')[0]
logo.setAttribute('src', 'http://www.google.cn/intl/zh-CN/images/logo_cn.gif')
logo.setAttribute('width', '286')
logo.setAttribute('height', '110')

2009年2月24日星期二

HTTP Basic 验证HTTPBasicAuthHandler

fanfou api 为例说明. 有兴趣的可以做个功能完整的工具.

#!/usr/bin/python
# coding=utf-8

import urllib2
import xml.dom.minidom
import winsound
import time
import thread
import urllib

public_timeline_url = "http://api.fanfou.com/statuses/public_timeline.xml"
user_timeline_url = "http://api.fanfou.com/statuses/user_timeline.xml"
friends_timeline_url = "http://api.fanfou.com/statuses/friends_timeline.xml"
statuses_update_url = "http://api.fanfou.com/statuses/update.xml"


# friendship related
friendships_create_url = "http://api.fanfou.com/friendships/create.xml"
friendships_destroy_url = "http://api.fanfou.com/friendships/destroy.xml"

# block list
blocks_create_url = "http://api.fanfou.com/blocks/create.xml"
blocks_destroy_url = "http://api.fanfou.com/blocks/destroy.xml"

passwd_mgr = urllib2.HTTPPasswordMgrWithDefaultRealm()
passwd_mgr.add_password(realm=None,
                          uri='http://api.fanfou.com/',
                          user='xxxxxxx',
                          passwd='xxxxxxxxx') # 用户名和密码

auth_handler = urllib2.HTTPBasicAuthHandler(passwd_mgr)
opener = urllib2.build_opener(auth_handler)

last_id = ''


def parseDom(doc):
    sts = doc.getElementsByTagName('status')
    get_textValue = lambda tag: \
        (lambda d:d.getElementsByTagName(tag)[0].childNodes[0].data)
    create_time = get_textValue('created_at')
    id_str = get_textValue('id')
    text = get_textValue('text')
    username = get_textValue('name')
    return [(username(node), text(node), create_time(node), id_str(node))
                for node in sts][::-1]

def refresh():
    global last_id
    print last_id
    res = opener.open(friends_timeline_url)
    doc = xml.dom.minidom.parseString(res.read())
    posts = parseDom(doc)
    id_list = [ids for (_, _, _, ids) in posts]
    if last_id in id_list:
        id_list = id_list[id_list.index(last_id)+1:]
        winsound.MessageBeep(winsound.MB_ICONASTERISK)
    print 
    for (user, txt, tm, ids) in posts:
        print "{%s}: %s [%s]" % (user, txt, tm.split()[3])
    last_id = posts[-1][-1]
    print 'MyMsg:',

def refresh_thread(times=0, timeout=60):
    f = False
    if times== 0:
        f = True
    while f or times:
        refresh()
        time.sleep(timeout)
    
def post_statue(msg, reply=''):
    if not msg:
        return
    #msg = unicode(msg, 'gbk')
    data = {'status' : msg,
            'in_reply_to_status_id' : reply,
            'source' : 'ffsh'}
    data = urllib.urlencode(data)
    opener.open(statuses_update_url, data)
  

thread.start_new_thread(refresh_thread, (0,30))

while True:
    mymsg = raw_input('MyMsg: ')
    post_statue( mymsg ) 
    

2009年2月22日星期日

用 python 暴百度贴吧

当然, 只是原型, 但基本功能有了. 目前在刷回帖的时候会有乱码, 编码问题需要解决. 成果展示: ---------------------------------------------------------------


#!/usr/bin/python
# -*- coding:utf-8 -*-

import urllib2
import urllib
import socket
import libxml2dom
import Image
import time



def domToQueryDict(doc, formIndex=0):
   data = {}
   form = doc.getElementsByTagName('form')[formIndex]
   nodes = form.getElementsByTagName('input')
   nodes.extend(form.getElementsByTagName('textarea'))
   for node in nodes:
       if node.hasAttribute('name') and node.getAttribute('type')!= u"submit":
           if node.hasAttribute('value'):
               data[node.getAttribute('name')] = \
                   node.getAttribute('value').encode('gbk', 'ignore')
           else:
               data[node.getAttribute('name')] = ""
   return data

             
cookie_handler = urllib2.HTTPCookieProcessor()
opener = urllib2.build_opener(cookie_handler)
urllib2.install_opener(opener)

# 获得登陆数据
url = "http://passport.baidu.com/?" + \
   "login&tpl=tb&u=http%3A//tieba.baidu.com/f%3Fkw%3Dpython"
doc = libxml2dom.parseString(opener.open(url).read(), html=1,
                            htmlencoding='gbk')
data = domToQueryDict(doc)

# 用户名/密码设置
data[u'username'] = '用户名'
data[u'password'] = '密码'

# 验证图片处理
veryfyPic = opener.open("https://passport.baidu.com/?verifypic")
picfile = file("pic.jpg", 'wb')
picfile.write(veryfyPic.read())
picfile.close()
im = Image.open("pic.jpg")
im.show()
data["verifycode"] = raw_input("What you see?").strip()

# 登陆页面
data = urllib.urlencode(data)
b = opener.open(url, data)  # here login OK
print b.read()
print '-'*20

for i in xrange(20):
   # 分析主页数据
   # url = "http://tieba.baidu.com/f?kz=543530949"
   b = opener.open("http://tieba.baidu.com/f?kw=python&t=1")
   frontpage = b.read()
   doc = libxml2dom.parseString(frontpage, html=1, htmlencoding='gbk')
             
   data = domToQueryDict(doc, 1)
   print "*",
   # 发贴标题及内容
   data[u'ti'] = "Fledna 自爆专用~!!!!!!!!!!!!!!"+str(i)
   data[u'co'] = "For Test only. " + str(i)
   print data[u'ti']
   data = urllib.urlencode(data)
   post_url = "http://tieba.baidu.com/f"
   b = opener.open(post_url, data)
   time.sleep(20)

2008年10月3日星期五

Pyton 字符串方法详解

本文最初发表于赖勇浩(恋花蝶)的博客(http://blog.csdn.net/lanphaday),如蒙转载,敬请保留全文完整,切勿去除本声明和作者信息。

在编程中,几乎90% 以上的代码都是关于整数或字符串操作,所以与整数一样,Python 的字符串实现也使用了许多拿优化技术,使得字符串的性能达到极致。与 C++ 标准库(STL)中的 std::string 不同,python 字符串集合了许多字符串相关的算法,以方法成员的方式提供接口,使用起来非常方便。 字符串方法大约有几十个,这些方法可以分为如下几类(根据 manuals 整理):
类型
方法
注解
填充
center(width[, fillchar]) ,
ljust(width[, fillchar]),
rjust(width[, fillchar]),
zfill(width),
expandtabs([tabsize])
l fillchar 参数指定了用以填充的字符,默认为空格
l 顾名思义,zfill()即是以字符0进行填充,在输出数值时比较常用
l expandtabs()的tabsize 参数默认为8。它的功能是把字符串中的制表符(tab)转换为适当数量的空格。
删减
strip([chars]),
lstrip([chars]),
rstrip([chars])
*strip()函数族用以去除字符串两端的空白符,空白符由string.whitespace常量定义。
变形
lower(),
upper(),
capitalize(),
swapcase(),
title()
title()函数是比较特别的,它的功能是将每一个单词的首字母大写,并将单词中的非首字母转换为小写(英文文章的标题通常是这种格式)。
>>> 'hello wORld!'.title()
'Hello World!'
因为title() 函数并不去除字符串两端的空白符也不会把连续的空白符替换为一个空格,所以建议使用string 模块中的capwords(s)函数,它能够去除两端的空白符,再将连续的空白符用一个空格代替。
>>> ' hello world!'.title()
' Hello World!'
>>> string.capwords(' hello world!')
'Hello World!'
分切
partition(sep),
rpartition(sep),
splitlines([keepends]),
split([sep [,maxsplit]]),
rsplit([sep[,maxsplit]])
l *partition() 函数族是2.5版本新增的方法。它接受一个字符串参数,并返回一个3个元素的 tuple 对象。如果sep没出现在母串中,返回值是 (sep, ‘’, ‘’);否则,返回值的第一个元素是 sep 左端的部分,第二个元素是 sep 自身,第三个元素是 sep 右端的部分。
l 参数 maxsplit 是分切的次数,即最大的分切次数,所以返回值最多有 maxsplit+1 个元素。
l s.split() 和 s.split(‘ ‘)的返回值不尽相同
>>> ' hello world!'.split()
['hello', 'world!']
>>> ' hello world!'.split(' ')
['', '', 'hello', '', '', 'world!']
产 生差异的原因在于当忽略 sep 参数或sep参数为 None 时与明确给 sep 赋予字符串值时 split() 采用两种不同的算法。对于前者,split() 先去除字符串两端的空白符,然后以任意长度的空白符串作为界定符分切字符串(即连续的空白符串被当作单一的空白符看待);对于后者则认为两个连续的 sep 之间存在一个空字符串。因此对于空字符串(或空白符串),它们的返回值也是不同的:
>>> ''.split()
[]
>>> ''.split(' ')
['']
连接
join(seq)
join() 函数的高效率(相对于循环相加而言),使它成为最值得关注的字符串方法之一。它的功用是将可迭代的字符串序列连接成一条长字符串,如:
>>> conf = {'host':'127.0.0.1',
... 'db':'spam',
... 'user':'sa',
... 'passwd':'eggs'}
>>> ';'.join("%s=%s"%(k, v) for k, v in conf.iteritems())
'passswd=eggs;db=spam;user=sa;host=127.0.0.1'
判定
isalnum(),
isalpha(),
isdigit(),
islower(),
isupper(),
isspace(),
istitle(),
startswith(prefix[, start[, end]]),
endswith(suffix[,start[, end]])
这些函数都比较简单,顾名知义。需要注意的是*with()函数族可以接受可选的 start, end 参数,善加利用,可以优化性能。
另,自 Py2.5 版本起,*with() 函数族的 prefix 参数可以接受 tuple 类型的实参,当实参中的某人元素能够匹配,即返回 True。
查找
count( sub[, start[, end]]),
find( sub[, start[, end]]),
index( sub[, start[, end]]),
rfind( sub[, start[,end]]),
rindex( sub[, start[, end]])
find()函数族找不到时返回-1,index()函数族则抛出ValueError异常
另,也可以用 in 和 not in 操作符来判断字符串中是否存在某个模板。
替换
replace(old, new[,count]),
translate(table[,deletechars])
l replace()函数的 count 参数用以指定最大替换次数
l translate() 的参数 table 可以由 string.maketrans(frm, to) 生成
l translate() 对 unicode 对象的支持并不完备,建议不要使用。
编码
encode([encoding[,errors]]),
decode([encoding[,errors]])
这 是一对互逆操作的方法,用以编码和解码字符串。因为str是平台相关的,它使用的内码依赖于操作系统环境,而unicode是平台无关的,是Python 内部的字符串存储方式。unicode可以通过编码(encode)成为特定编码的str,而str也可以通过解码(decode)成为unicode。

2008年10月2日星期四

强悍的类定义

>>> class Config(object):
...     def __init__(self, **kw):
...         self.__dict__.update(kw)
...

那么:

>>> cfg = Config(host = '127.0.0.1', port = '8080')
>>> print "%s:%s"%(cfg.host, cfg.port)
127.0.0.1:8080

更变态版本:

>>> def Config(**kw):
...     obj = type('Config', (), kw)()
...     return obj
...
 
>>> c = Config(host = '127.0.0.1', port = '8080')
>>> c.host, c.port
('127.0.0.1', '8080')

来自: http://blog.csdn.net/lanphaday/archive/2008/09/09/2905877.aspx

2008年9月18日星期四

使用PyWin32将CherryPy应用安装为服务

CherryPy + PyWin32 应用 老版本的 cherrypy
# coding=cp936 import cherrypy import win32serviceutil import win32service import win32event
class HelloWorld: """ 请求句柄例子 """ # 暴露对象 @cherrypy.expose def index(self): # 只做测试用,所以只返回简单内容 return "Hello world!"
class MyService(win32serviceutil.ServiceFramework): """NT 服务""" # 服务名 _svc_name_ = "CherryPyService" # 服务显示名称 _svc_display_name_ = "CherryPy Service"
def __init__(self, args): win32serviceutil.ServiceFramework.__init__(self, args) # 创建一个事件 self.stop_event = win32event.CreateEvent(None, 0, 0, None)
def SvcDoRun(self): cherrypy.root = HelloWorld() # 更新配置,当使用配置文件时,必须为一个绝对路径 cherrypy.config.update({ 'global':{ 'server.socketPort' : 81, 'server.environment': 'production', 'server.logToScreen': False, 'server.log_file': 'e:\\edit\\log.txt', 'server.log_access_file': 'e:\\edit\\log.txt', 'autoreload.on' : False, 'server.logTracebacks' : True } }) # 设置 initOnly=True cherrypy.server.start(initOnly=True) win32event.WaitForSingleObject(self.stop_event, \ win32event.INFINITE) def SvcStop(self): self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING) cherrypy.server.stop() win32event.SetEvent(self.stop_event)
if __name__ == '__main__': win32serviceutil.HandleCommandLine(MyService)
P.S.假设文件名为mysrv.py 则
x:\> mysrv.py --显示所有可用命令选项
mysrv.py install --安装服务
mysrv.py start --启动服务
mysrv.py stop --停止服务
mysrv.py restart --就是restart,重启,更新代码用
mysrv.py remove --删除服务
再P.S.测试时候一定要注意防火墙,服务是自动拦截的(pythonservice.exe).偶就在这里出问题了~嘻嘻
用到的路径必须全为绝对路径,静态目录也是
安装好服务后,也可以使用net start/stop CherryPyService 来管理