PYTHON后台开发小结

来源:互联网 发布:网络ip电话如何安装 编辑:程序博客网 时间:2024/05/31 13:15

先整理几个感觉不错的技术点

1.  Epoll

    基本上,Epoll的使用和linux类似:首先声明一个epoll对象select.epoll()Poll()用于提取时间段内的事件,register()用于注册socket以及选择侦听什么事件,modify()用于改变对一个socket的侦听的事件,unregister()则是把socket移出侦听队列中。常用事件包括EPOLLIN, EPOLLOUT, EPOLLHUP

    顺便说说epoll的优点,主要有支持一个进程打开大数目的socket描述符,IO效率不随FD数目增加而线性下降,使用mmap加速内核与用户空间的消息传递,内核微调。第一个优点相信在开发多进程的程序里会有所体会,比如当程序需要管理许多进程间通信的pipe,管理许多socket,管理file descriptionfd)的时候epoll就比select好用(select默认打开的fd不超过1024个)。此外其他三个优点在写程序时候是感觉不到的,但是它们都说明了epoll相比selectpoll等传统异步方式要好。

说到epoll,还得扯一下边沿触发和水平触发机制。在边沿触发模式中,epoll.poll()在读或者写event在socket上面发生后,将只会返回一次event。调用epoll.poll()的程序必须处理所有和这个event相关的数据,随后的epoll.poll()调用不会再有这个event的通知。当一个特定event的数据耗尽时,进一步尝试操作socket将导致一个异常。相反,在水平触发模式下,重复调用epoll.poll()会重复通知关注的event,直到与该event有关的所有数据都已被处理。在水平模式下通常没有异常。

Epoll的具体用例:http://zoomquiet.org/res/scrapbook/ZqFLOSS/data/20100927213110/

2. Multiprocessing

2.1 多进程

    多进程可以通过os包,采用类似linux下的方法进行,即fork()方式。不过PYTHON2.6以后为我们提供了专用的多进程包,Multiprocessing。具体使用方法可以参照下文:

http://www.cnblogs.com/vamei/archive/2012/10/12/2721484.html

http://www.cnblogs.com/vamei/archive/2012/10/11/2720042.html

    其中Process()用于声明子进程服务函数及传递参数,start()用以启动子进程,join()类似于linuxwait(),在UNIX平台上,当某个进程终结之后,该进程需要被其父进程调用wait,否则进程成为僵尸进程(Zombie)。所以,有必要对每个Process对象调用join()方法。    

2.2 进程池

进程池(pool)的用法和上述多进程的用法相类似。Pool()用于声明打开的进程数,常用的方法有:

apply_async(func,args)  从进程池中取出一个进程执行funcargsfunc的参数。它将返回一个AsyncResult的对象,你可以对该对象调用get()方法以获得结果。

close()  进程池不再创建新的进程

join()   wait进程池中的全部进程。必须对Pool先调用close()方法才能join

相比常规的多进程模型,进程池模型主要在于进程数目可控,对于维护和管理服务器流量有较好的效果。

参考:http://www.cnblogs.com/vamei/archive/2012/10/13/2722254.html

2.3 共享内存

    multiprocessing提供了threading包中没有的IPC(比如PipeQueue),效率上更高。应优先考虑PipeQueue,避免使用Lock/Event/Semaphore/Condition等同步方式 (因为它们占据的不是用户进程的资源)

多进程应该避免共享资源。在多线程中,我们可以比较容易地共享资源,比如使用全局变量或者传递参数。在多进程情况下,由于每个进程有自己独立的内存空间,以上方法并不合适。此时我们可以通过共享内存Manager的方法来共享资源。但这样做提高了程序的复杂度,并因为同步的需要而降低了程序的效率。

(1)Pipe可以是单向(half-duplex),也可以是双向(duplex)。我们通过mutiprocessing.Pipe(duplex=False)创建单向管道 (默认为双向)。一个进程从PIPE一端输入对象,然后被PIPE另一端的进程接收,单向管道只允许管道一端的进程输入,而双向管道则允许从两端输入。

(2)QueuePipe相类似,都是先进先出的结构。但Queue允许多个进程放入,多个进程从队列取出对象。Queue使用mutiprocessing.Queue(maxsize)创建,maxsize表示队列中可以存放对象的最大数量。

3. List & dict

List是颇具PYTHON特色的数据结构之一。其与C中的数组类似,却又优于数组(所以PYTHON里面是木有Array这个概念的,因为我们有List)。其最大特点在于,list里面的每一个元素都可以是任意类型的值,比如a=[123,“abc”,False]

DictionaryPYTHON另一个很有特色的数据结构(尽管JSPHP上面已经有JSON这个玩意儿)。Dictionary最大的特点在于其存储是以key-value形式进行的,这使得在执行一些search操作的时候方便了许多(对于DB来说,性能的瓶颈往往就在于search操作上)。同List一样,所有valuekey可以以不同类型存在(无类型就是强大)。附带一句,PYTHON是木有switch的,why?那是因为dictionary完全可以实现switch咯,哈哈。

也许我的轻描淡写不足以让你感觉这两个小小的数据结构有神马值得你excited的地方,那试着用用他们就知道了(尝试嵌套使用)。当然,加上下面提到的PYTHON的辅助格式处理的包,就会更牛叉了。

P.S. 其实PYTHON特色的数据结构还有stringtuplestringC++的差不多就不多赘述了,tuple还没怎么用过,看《PYTHON core programming》上面说,是一种类型不可变的数据类型,这是对于key的查找和hash是很好的一个性质,呵呵,以后用到再总结了。

参考:《PYTHON core programming

4. Json & pickle & shelve

4.1 json

JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。Json是个好东西,他的存在让应用层的数据传输变得简单许多,通过json.dumps()将简单数据类型(如intdictionarylisttuple等)进行编码,转成字符串形式再交付给传输层进行数据传输,在接收端只需对接收到的字符串通过json.loads()还原,即可得到原来的数据类型。

此外json包还提供了一些额外的辅助函数,不过多数场合下使用dumps()loads()就可以了。

参考:http://www.cnblogs.com/coser/archive/2011/12/14/2287739.html

4.2 pickle

当数据交换不是发生在客户端与服务器之间,不是所谓的在传输层交换数据,而是本地的和文件交换数据时,为了方便存取,有时也需要做必要的编解码。对此可以用picklecpickle包进行操作,他可以将对象直接存储到磁盘文件上,以便以后检索,这就是所谓的对象持久性机制。同样的,它也是用dumps()和loads()完成基本的编解码操作。

参考:http://www.cnblogs.com/cobbliu/archive/2012/09/04/2670178.html

4.3 shelve

如果不喜欢用pickle做数据持久化的工作,那么还可以用shelveShelvePython中为我们提供了一个简易的数据库,其操作十分简单,与对dictionary的操作有点类似,具体可以参照:http://www.cnblogs.com/hengli/archive/2012/05/23/2515386.html

5. Other useful message

1str()一般是将数值转成字符串。 
     repr()是将一个对象转成字符串显示,注意只是显示用,有些对象转成字符串没有直接的意思。

2Try...Catch...Finally异常处理

3TCPPYTHONTCPUDP传输基本和LINUX一致,就不过多赘述了。这里需要说明的是PYTHON还提供了一个TCPSERVER包,里面有基于TCP传输的并行服务器的模型,如果只是写个小服务器,基本上这个包是可以直接使用的了。

4)话说PYTHON有数据库,有socket,有json,有持久化机制,有进程池,有epoll......这么多好玩的东西,那么,有木有http服务器呢?嘻嘻,在末尾这里告诉你,也是有的,这里放上一个链接供大家参考:http://bottlepy.org PYTHON极轻量级http服务器。

顺便留个问题:PYTHON如何在进程间传递file description呢?

原创粉丝点击