concurrence vs twisted ---- python networking/concurrence library/framework

python concurrence framework/library : http://wiki.python.org/moin/Concurrency/

栈溢出对该问题的讨论帖:http://stackoverflow.com/questions/1824418/a-clean-lightweight-alternative-to-pythons-twisted


concurrence

1.并行编程

2.所有程序运行在tasklet中,由disptach启动第一个tasklet,内部可以衍生出多个tasklet

3.tasklet.sleep(x)可以出让CPU,time.sleep(x)会阻塞整个进程;不出让CPU的情况下所有tasklet串行(序列化执行,且每个tasklet执行完了才到下一个tasklet);Tasklet.loop(func)指定的func如果内部没有Tasklet.sleep(x)调用,就会导致整个进程陷入这个函数的死循环中;Tasklet.yield_()也可以出让CPU,在CPU密集且没有阻塞事件的tasklet内部一定要在循环中调用该方法出让CPU(http://opensource.hyves.org/concurrence/concurrence.core.html#concurrence.core.Tasklet.yield_)


twisted ( module index)( start here)

1.事件驱动编程:异步,基于回调编程(不同于有阻塞代码或者用线程去运行阻塞代码的程序),函数都是立刻返回,然后当数据可用时启动一串回调

2.twisted.internet.protocol.Protocol:Protocol class随着每个连接而实例化一个对象;随着连接结束而消失。connectionMade连接建立的事件,connectionLost连接断开的事件,dataReceived新数据事件。loseConnection()在数据发送完毕后才关闭连接,abortConnection()直接掐断连接。

3. twisted.internet.protocol.Factory:一致化的配置(持久数据)由Factory提供,其buildProtocol方法为每个新的连接创建一个Protocol对象。Factory不监听端口,因为我们可能需要对不同地址和端口提供一样的服务,Factory不需要知道网络的事情。网络监听相关的事情由endpoints相关的概念提供(ListenTCP,reactor)。Factory要实现应用程序指定的初始化和结束业务,可在startFactory()和stopFactory()内部完成,不能__init__和__del__中做,因为Factory一般是全程不消逝的实例。

4.endpoint监听端口,reactor.run()启动反应堆。reactor.stop() or ctrl+c 终止反应堆。

5.http协议是LineReceiver 和 rawDataReceived的混合体。对于LineReceiver protocol有两个不同的事件处理函数,lineReceived 和 rawDataReceived,调用setRawMode()之后新数据到来会调用rawDataReceived ,直到 setLineMode()被调用才会切换到 lineReceived。 sendLine函数发送的数据加上行分隔符(默认\r\n)。

6.两种client编程方式(a更灵活,从factory往下都是一致的,要改变协议和地址端口只需修改endpoint相关逻辑;b更可控,有一些endpoint还不支持的low-level的操作,比如reconnection):a.endpoint,connect,这种模式connect传入的必须是Factory而不能是ClientFactory; b.ClientFactory,reactor

7.单元测试,Test-Driven Development(TDD)->write tests first, make sure they fail, then do development.

8.application, twistd -y service.tac


concurrence vs twisted

1.concurrence有我中意的stackless+libevent,但是过于简陋,在耗时的阻塞操作(一个tasklet阻塞住整个进程循环就会阻塞住)转异步操作上比较麻烦,比如调用第三方库提供的接口(urllib2.urlopen(xx).read()),没有直观的异步机制(官方文档显示数据库查询已经实现异步了,没试过),twisted没有这个问题(可以用Deferred/deferToThread/callInThread等解决)

2.concurrence没有twisted的protocol这个东东(twisted.internet.protocol.Protocol),从网络收到的数据需要自己读取和解析不像twisted一样有数据准备好的事件处理函数(myProtocol.dataReceived()/myProtocol.LineReceived())、对于连接断开和建立成功也没有封装好的事件处理函数(myProtocol.connectionMade()/myProtocol.connectionLost()),都需要自己从零做起,比较耽误时间

3.但是,twisted好庞大,这算是twisted对我而言难搞的主要问题,尤其是其TDD、twistd部署(tac文件)、各种封装好的协议(MAIL/DNS/SSL/..)、官网上手册上那个什么"Tutorial: Twisted From Scratch"之类的,一点都不想花心思了解

4.为了用上multiple cpu,两者都需要引入多进程。twisted比较方便:twisted.internet.utils.getProcessOutput()/getProcessValue()执行子进程并拿到输出或返回值(Deferred异步);twisted.internet.reactor.spawnProces()发动子进程+twisted.internet.protocol.ProcessProtocol协议用事件处理函数(connectionMade/terminateProcess/outReceived/errReceived/...)的方式跟子进程交互。上述这些concurrence是没有的。而对于跟子进程以外的进程交互,比较简单的方式是用tcp连接来做,那么两者对比就回到了前面提过的点上了(concurrence对连接建立/断开/数据到达等没有做封装和提供事件处理函数)

5.还有个问题是两者都没有ORM,数据库操作比较麻烦,如果能把django的ORM集成进来就爽歪歪了,貌似django-twisted是干这活的,待老衲进去一探究竟?

---> [2013.6.24] 结果出炉,django-twisted(twango)这个项目已经老得跟不上django的步伐了(最近更新是两年前)。据推测,当年django中count()/all()/none()跟filter()一样可接收扩展位置参数和扩展关键字参数,README中的代码需要改成下述样子才可正常运行(TwistedQuerySet中连filter这些方法都没有更说明twango这个项目很古老并且已被人抛弃):

import sys
sys.path.append('/home/dongsong/boosencms/src/')
import os
if not os.environ.has_key('DJANGO_SETTINGS_MODULE'):
        os.environ['DJANGO_SETTINGS_MODULE'] = 'boosencms.settings'
else:
        print 'DJANGO_SETTINGS_MODULE: %s' % os.environ['DJANGO_SETTINGS_MODULE']
from boosencms.weibo.analysis.models import WomWeiboSina
from twango.manager import TwistedManager
from django.db.models.manager import Manager
from twisted.internet import reactor
from twisted.internet.defer import Deferred
import logging
logging.basicConfig(level = logging.INFO, format = "%(asctime)s %(levelname)s [%(filename)s:%(lineno)d]%(message)s")

class TwistedWeiboSina(WomWeiboSina):
    objects = Manager()
    twisted = TwistedManager()

    class Meta:
        app_label = 'analysis'
        proxy = True


def count_me(count):
    print "Count: %s" % count

def all(queryset):
    print 'All: %s' % queryset

def none(queryset):
    print 'None: %s' % queryset

def filter(queryset):
        print 'Filter: %s' % queryset

def callback(*args, **kwargs):
        TwistedWeiboSina.twisted.get_query_set().count(success_callback = count_me)
        TwistedWeiboSina.twisted.get_query_set().all(success_callback = all)
        TwistedWeiboSina.twisted.get_query_set().none(success_callback = none)
        TwistedWeiboSina.twisted.filter(createTime__gte = '2013-06-01', success_callback = filter)

d = Deferred()
d.addCallback(callback)
d.callback(None)
#callback()

reactor.run()

twango源码query.py的class TwistedQuerySet中需要加上filter的处理

def filter(self, **kwargs):
        return self._super_threaded('filter', **kwargs)



你可能感兴趣的:(concurrence vs twisted ---- python networking/concurrence library/framework)