Django, 不错

http://tenyears.cn/index.php?cat=6&paged=2
  比较客观的语言性能比较
Friday, October 26th, 2007

上经常有一些语言大对比,C/C++ VS Java, Python VS Ruby等,其实这些都很无聊的,只能当作饭后谈资了,因为没有最好的语言,只有最合适的语言。每种语言都有自己的用武之地,存在就是有道理的。

无疑中发现了这个网站,用于比较各种语言的性能的,以C语言为参照物,各种语言与C比较,速度慢多少。从中可以看出比较有意思的结论,C++与C不相上下,Java语言的性能也非常高,而脚本语言中,算Lua最高了,也是,它本身就很小巧。而在Python、Perl、PHP、Ruby之间,还是Python排名最高了,不过前三者之间差距不大,而Ruby的排名就比较后了。

这种比较还是很客观的,利用了各种常用的算法计算所耗费的时间,用同一套规则判断,总比网上一些头脑发热的比较来的有说服力一些。

Django, 不错

Thursday, October 25th, 2007

近在做需求分析时需要一个轻量级的WebServer,这里轻量级的意思是小巧、开发和部署容易,由于现在项目中大量使用了Python脚本,所以重点放在了Python编写的WebServer上。在实际衡量不同的WebServer后,发现Django非常不错,虽然现在还是0.96版本,还未到正式发布状态,但其功能和API都已经趋于稳定,可以适当考虑一下。

说起Django,大家会与ROR对比,的确,Django与ROR有太多的相识之处,比如ORM、模板、MVC、无XML文件、Url Rewrite等,或许Django是用Python开发的,所以从心里感觉很好,而不像ROR那样不适,也许是先入为主的原因吧。

与ROR不同的是,Django还有许多特色之处,比如Cache,更加灵活的模板技术、插件技术等,这些都很具有创意。

有时间就好好研究一下,除了ROR外的又一个选择。

YouTube也用Python?

Thursday, July 26th, 2007

界上最受欢迎的视频网站YouTube每天的流量是惊人的,经常去浏览的人应该很熟悉YouTube的“维护通知”。很多人肯定对网站的架构很好奇,上个月在西雅图召开的扩展性技术研讨会上,YouTube的技术主管Cuong Do就此作了一个演讲,下面内容引用自相关的中文介绍。

YouTube大部分代码都是用Python开发,用MySQL存储元数据--用户信息,Web服务器部分是Apache,用FastCGI模式。视频内容则用Lighttpd。 视频的缩略图(Thumbnails)给服务器带来了很大的负担。每个视频平均有4个缩略图,Web页面上更有多个,每秒钟带来的磁盘IO请求太大。技术 人员启用了单独的服务器群组来承担压力,并且针对Cache和OS做了部分优化。另一方面,缩略图请求的压力导致Lighttpd 性能下降。通过 Hack Lighttpd 增加更多的worker 线程在很大程度解决了问题。而最新的解决方案是起用了Google的BigTable。

从整个架构来看,依然使用了非常普遍而且“廉价”的技术。由于Google很热衷Python,所以YouTube使用Python也就不以外了。

Python多线程中popen的问题

Sunday, June 24th, 2007

近在Python多 线程中调用HP-UX系统命令时,出现进程死锁的问题,主要是运行一些运行时间比较长的程序,比如ping、sar等,而且这与操作系统的版本还有关系, 不是所有的操作系统和版本存在这个问题。在网上也找到了有类似问题的Bug,但好像Python并没有改正,目前还不知道是Python多线程的问题还是 popen的问题,在没有新版本之前,这个问题还是要解决的。

由于这类问题只有在多线程中出现,而在主线程中却不存在,其结果都能正常输出。所以只有在多线程中将需要运行的命令提交给主线程执行,把结果再返回给子线程,看样子,目前也只有这个解决方案了。该方案在测试中也非常正常,唯一需要注意的是主线程在运行命令时会阻塞的。

SOAPPy编写SOAP服务

Monday, March 12th, 2007

前使用过Java和Perl编写SOAP服务,还比较简单的,对应的库有Axis和SoapLite。最近由于一个项目大部分使用Python作为开发语言,考虑使用Python来编写SOAP对外提供服务。众所周知,Python的动态和简单是出了名的,用它编写SOAP服务也相当简单的,要比Java和Perl来得更轻松。

使用Python编写SOAP,可以下载SOAPPy库。

编写SOAP服务,用于获得服务器当前的时间:

import sys
sys.path.insert (1, '..')
from SOAPpy import *
import time

def gettime():
    return time.strftime('%Y-%m-%D %H:%M:%S', time.localtime())

namespace = 'http://tenyears.cn/'
server = SOAPServer (("localhost", 9000))
server.registerKWFunction (gettime, namespace)
try:
    while True:
        server.handle_request()
except KeyboardInterrupt:
    pass

以下是访问该SOAP服务的客户端测试代码:

import sys
sys.path.insert (1, '..')
from SOAPpy import *

endpoint = "http://localhost:9000/"
ns = "http://tenyears.cn/"
serv = SOAPProxy(endpoint, namespace=ns)
print serv.gettime()

与其他语言相比,这已经简化了许多,而且可以在不用编写本地代码的情况下就直接调用SOAP服务的方法,这和访问本地服务一样,非常的轻松。现在唯一担心的是它的性能,因为简单一定会带来其他的问题。但对于目前而言,可以暂时不用考虑这个。

使用Python访问Windows的注册表

Friday, January 26th, 2007

使用Python访问Windows的注册表

Python的标准库中,_winreg.pyd可以操作Windows的注册表,另外第三方的win32库封装了大量的Windows API,使用起来也很方便。不过这里介绍的是使用_winreg操作注册表,毕竟是Python自带的标准库,无需安装第三方库。

下面的例子是通过Python获取Windows XP下已经安装的补丁号。Windows的补丁号都在“HKEY_LOCAL_MACHINE/SOFTWARE//Microsoft// Updates”下,通过循环下面所有的目录节点,如果找到的名称符合正则表达式KB(/d{6}).*,则表示是一个补丁号。

从例子可以看出操作起来非常的简单和快速。

# -*- coding: utf-8 -*-
# 获取Windows的已打的补丁号
from _winreg import *
import re

def subRegKey(key, pattern, patchlist):
    # 个数
    count = QueryInfoKey(key)[0]
    for index in range(count):
        # 获取标题
        name = EnumKey(key, index)
        result = patch.match(name)
        if result:
            patchlist.append(result.group(1))
        sub = OpenKey(key, name)
        subRegKey(sub, pattern, patchlist)
        CloseKey(sub)

if __name__ == '__main__':
    patchlist = []
    updates = 'SOFTWARE//Microsoft//Updates'
    patch = re.compile('(KB/d{6}).*')
    key = OpenKey(HKEY_LOCAL_MACHINE, updates)
    subRegKey(key, patch, patchlist)
    print 'Count: ' + str(len(patchlist))
    for p in patchlist:
        print p
    CloseKey(key)

用Python实现任务队列

Monday, January 22nd, 2007

起任务队列,Java中的concurrent应该是这方面的杰出代表,可以参考我以前写的Blog。我这里想说的是用Python实现的任务队列。

在Python的标准库中没有任务队列,不过可以参考Java的实现,自己做一个任务队列。任务队列主要由三个方面组成:
1) 优先队列(PriorityQueue),用于将最近需要执行的任务放到前面。一般使用Heap,也可以参考我写的Blog。
2) 阻塞队列,在Java的实现中,是以内嵌一个优先队列实现的。不过在我的Python实现中,是直接从优先队列继承而来。主要关注点是取出一个任务(优先队列的最优解)时,如果时间未到,必须要睡眠等待。
3) 延迟任务,任务的执行体。提供了prerun(),run()和postrun()方法。继承类需要实现run()

关于延迟任务,主要有以下属性:
1) 下次执行的时间。当下次执行的时间小于或者等于当前时间时,就要执行了。反之,则等待。
2) 两次任务执行的间隔时间。
3) 任务运行模式。

关于任务运行模式有以下三种情况:
1) 周期性。即每隔一段时间执行该任务。比如每10分钟执行一次任务。
2) 间隔性。即第一次任务执行完成后,隔一段时间再执行该任务,比如每任务间隔10分钟执行。
3) 一次性。即该任务只执行一次。

如果实现了以上的一些特性,一个任务队列就实现了。

不过有一个很实际的问题:如何退出任务队列,即使当前有任务还没有运行?这里使用了一个技巧:向任务队列里投放一个ExitTask的任务队列,该任务的执行时间就是当前时间,所以它会马上执行,当线程发现是ExitTask时,就退出线程。

另外以前是把代码保存到本机上,在换电脑或者搬迁后这些代码就不见影踪了。现在就把代码放到了Google Code上去。申请还是很方便的,我就为这个简单的代码申请了一个pytask.

下面是一个测试代码:

from threading import Thread
from pytask.task import *
from time import sleep, time

class MyTask(DelayedTask):
    def run(self):
        print 'Execute the task…'
        sleep(3)

class Test(Thread):
    def __init__(self, dq, name='Test'):
        Thread.__init__(self)
        self.dq = dq;
        self.setName(name)

    def run(self):
        while True:
            task = self.dq.take()
            if task.isExit():
                print 'Thread is going to shutdown now.'
                # put the logo back to queue so other theads can exit
                pq.put(task)
                break
            task.preRun(self.dq)
            print self.getName() + ' ' + str(task)
            task.run()
            task.postRun(self.dq)

class Add(Thread):
    def __init__(self, dq, name='Test'):
        Thread.__init__(self)
        self.dq = dq;
        self.setName(name)

    def run(self):
        for index in range(size):
            import random
            r = random.randint(5, size)
            sleep(1)
            task = MyTask(time() + r, r, 'Task' + str(index))
            print task
            pq.put(task)
        sleep(100)
        # after 100s exit
        pq.put(ExitTask)

if __name__ == '__main__':
    d = []
    # 200 tasks
    size = 200
    # 延迟队列
    pq = DQueue()

    # 5个执行线程
    take = Test(pq, 't1-')
    take.start()
    take = Test(pq, 't2-')
    take.start()
    take = Test(pq, 't3-')
    take.start()
    take = Test(pq, 't4-')
    take.start()
    take = Test(pq, 't5-')
    take.start()
    # 添加任务
    add = Add(pq, 'A--')
    add.start()

使用PySNMP还是比较简单的

Wednesday, January 10th, 2007

各种网络协议中,SNMP算是比较简单的,但使用也很广泛。目前对SNMP的实现主要有snmp++,它使用C++开发,跨平台,使用上也比较简单。不过虽然是C++开发的,其有良好的面向对象性,但开发效率和实施上与动态脚本相比还是差了一些。

PySNMP就是用纯Python开发的SNMP包。整个包很小,才120K,不过它依赖asn1库,到PySNMP的官方网站上就可以下载这些依赖库。

先用PySNMP获得SNMP信息吧:

from pysnmp.entity.rfc3413.oneliner import cmdgen
errorIndication, errorStatus, errorIndex, varBinds =/
    cmdgen.CommandGenerator().getCmd(
    cmdgen.CommunityData('my-agent', 'public', 0),
    cmdgen.UdpTransportTarget(('localhost', 161)),
    (1,3,6,1,2,1,1,1,0)
    )
print varBinds

再用PySNMP发一个告警Trap:

# Notification Originator Application (TRAP)
from pysnmp.carrier.asynsock.dispatch import AsynsockDispatcher
from pysnmp.carrier.asynsock.dgram import udp
from pyasn1.codec.ber import encoder
from pysnmp.proto import api

# Protocol version to use
verID = api.protoVersion1
pMod = api.protoModules[verID]

# Build PDU
trapPDU =  pMod.TrapPDU()
pMod.apiTrapPDU.setDefaults(trapPDU)

# Traps have quite different semantics among proto versions
if verID == api.protoVersion1:
    pMod.apiTrapPDU.setEnterprise(trapPDU, (1,3,6,1,1,2,3,4,1))
    pMod.apiTrapPDU.setGenericTrap(trapPDU, 'coldStart')
    var = []
    oid = (1,3,6,1,1,2,3,4,1,1)
    val = pMod.OctetString('Error Type')
    var.append((oid,val))
    oid = (1,3,6,1,1,2,3,4,1,2)
    val = pMod.OctetString('Error Info')
    var.append((oid,val))
    pMod.apiTrapPDU.setVarBinds(trapPDU, var)

# Build message
trapMsg = pMod.Message()
pMod.apiMessage.setDefaults(trapMsg)
pMod.apiMessage.setCommunity(trapMsg, 'public')
pMod.apiMessage.setPDU(trapMsg, trapPDU)

transportDispatcher = AsynsockDispatcher()
transportDispatcher.registerTransport(
    udp.domainName, udp.UdpSocketTransport().openClientMode()
    )
transportDispatcher.sendMessage(
    encoder.encode(trapMsg), udp.domainName, ('localhost', 162)
    )
transportDispatcher.runDispatcher()
transportDispatcher.closeDispatcher()

看到了吧,使用上还是比较简单的,这对于测试SNMP协议以及在大多数场景下都可以得到很好应用。从某种程度上看,它也是跨平台的。

PyRun_SimpleFile的问题

Monday, January 8th, 2007

Windows下将Python嵌 入到C/C++中最简单的方法就是使用PyRun_SimpleFile函数了,但如果设置不正确,会造成“非法指针”,而使程序宕掉。其中主要原因是链 接运行库的方法不对,造成了运行时文件操作时文件指针出现错误,虽然问题比较简单,但如果不知道方法会给定位问题带来麻烦。

一般而言,应用程序要和Python库链接方法一致。比如Python是动态库(DLL),链接的运行库也是多线程动态库(/MD),则你的应用程序也必须链接相同的运行库.

#include <Python.h>

int main(int argc, char *argv[])
{
    Py_Initialize();
    FILE *fp = fopen("1.py", "r");
    if(fp != NULL) {
        PyRun_SimpleFile(fp, "1.py");
        fclose(fp);
    }
    Py_Finalize();
    return 0;
}

编译:cl /O /ID:/Python25/include /DWIN32 /MD PySimple.cpp /link /LibPath:D:/Python25/libs

需要注意的是:Python发行版本库中自带的Python25.dll使用的MSVCR71.dll,而我用的是VS2005,默认使用MSVCR80.dll,造成了运行出错。不过使用VS2005重新编译Python25并且替换原来其库后,就变得正常了。

如果想偷懒,可以采用Python的官方网站上推荐方法。
PyRun_SimpleString("execfile('1.py')");

奇怪的是为什么Python不提供Windows下的静态库呢?就像Unix和Linux下一样。

编译技术

Saturday, September 2nd, 2006

能对我来说,编译技术是一门神秘的技术,以前也只听说过Lex&Yacc工具,但没有具体用过,毕竟实际工作中用得不多,或者可以用的太多了,没有必要自己去整一套自己的语言。

但最近工作中需要使用编译技术来实现规则,所以也硬着头皮去看《编译原理》。不过理论的东西学起来很费劲,还是从实践中来到实践中去。目前对我而言,会用就可以了,至于为什么这么用,那是以后的事情。

在开源世界中,使用编译技术的软件还很多,它们大都是大同小异,原理都是相同的。目前可下载的这类源代码有Eclipse的JDT、Python、Lua和SWIG。

奇怪的是,除了SWIG使用Bison作为工具来自动生成代码外,其他的都是手工实现了词法分析和语法分析。这让我感到很惊讶,为什么工具不用,而去手工实现呢?估计还是不相信工具生成的代码,或者从性能方面和维护方面考虑吧。

Eclipse的JDT更不用说了,它完全实现了Java的编译器,性能也不错。另外在JDT中可以看到很多代码优化的例子,对于编写高性能的解释器和编译器是很有帮助的。

至于Lua,使用它的软件一大把,可见它的优势很明显,Lua的源代码是最简洁的,词法分析和语法分析加起来来也只有2000行代码,所以它应该是学习编译技术最好的例子了。代码也比较简单,看起来也很快,另外它提供了完整的分析文档,这是很难得的。

Java和Python使用了中间代码的技术,即将源代码编译成中间代码,但 实际上Python的源代码的执行速度和中间代码的速度是相同的(Python的文档描述)。Java是一种很复杂的语言,所以它的编译器也是非常复杂 的,还好有Eclipse IDE,研究起来非常方便的。

总体来说编译技术是一种非常复杂的技术,其中有很多优秀的思想、算法,所以值得一学。

你可能感兴趣的:(django,python,SOAP,任务,OpenSource,Comments)