原文发表在我的 博客主页 ,转载请注明出处!
建议四十一:一般情况下使用ElementTree解析XML
python中解析XML文件最广为人知的两个模块是 xml.dom.minidom 和 xml.sax ,作为主要解析XML方法的两种实现,DOM需要将整个XML文件加载到内存中并解析为一棵树,简单但是内存消耗大;SAX是基于事件驱动的,虽不需要全部装入XML文件,但是处理过程复杂。一般情况下选择 ElementTree 便可以, cElementTree 是其Cython实现,速度更快,消耗内存更少,性能上更好。使用 ElementTree 的特性有:
建议四十二:理解模块pickle优劣
python中有很多支持序列化的模块,像pickle,json等
序列化,就是把内存中的数据结构在不丢失其身份和类型信息的情况下转成对象的文本或二进制表示的过程,比如在磁盘上保存当前程序的状态数据以便重启的时候能够重新加载,多用户或者分布式系统中数据结构的网络传输时,可以将数据序列化后发送给一个可信网络对端,接收者进行反序列化后便可以重新恢复相同的对象等
pickle是最通用的序列化模块了,他主要有两个函数 dump() 和 load() ,分别用来进行对象的序列化和反序列化,函数定义如下:
import cPickle as pickle my_data = {"name" : "Python", "type" : "Language", "version" : "2.7.5"} fp = open("picklefile.dat","wb") pickle.dump(my_data, fp) fp.close() fp = open("picklefile.dat","rb") out = pickle.load(fp) fp.close() print out print type(out)
pickle拥有良好的特性:
import cpickle as pickle a = [1, 2] b = a b.append(3) p = pickle.dumps((a, b)) a1, b1 = pickle.loads(p) print a1, b1 a1.append(4) print b1
建议四十三:序列化的另一个不错的选择——JSON
JSON(JavaScript Object Notation)是一种轻量级数据交换格式。相对于上文提到的pickle,JSON有如下优势:
gList = ['a','b','c','d','e','f','g'] def f(): gList[5] return g() def g(): return h() def h(): del gList[2] return i() def i(): gList.append('i') print gList[7] if __name__ == '__main__': try: f() except IndexError as ex: print "Sorry,Exception occured,you accessed an element out of range" print ex
这个例子比较简单,开发人员也为自己和用户打印出了错误信息,但是如果要debug,怎么才能快速地知道错误发生在哪里呢?traceback模块可以满足这个需求,它会输出完整的栈信息,将上面的代码修改下:
except IndexError as ex: print "Sorry,Exception occured,you accessed an element out of range" print ex traceback.print_exc()
再次运行,程序会输出发生异常时候完整的栈信息,包括调用顺序、异常发生的语句、错误类型等。
traceback.print_exc()方法打印出的信息包括3部分:错误类型、错误对应的值以及具体的trace信息,包括文件名、具体的行号、函数名以及对应的源代码。
*
建议四十五:使用logging记录日志信息**
logging模块提供了日志功能,将logger的level分为5个级别,如下图,可以通过Logger.setLevel(lvl)来设置,默认的为WARNING
logging lib包含了以下4个主要对象:
关于logging的使用:
import logging logging.basicConfig(level = logging.DEBUG) logger = logging.getLogger(__name__)
import threading, time,sys class test(threading.Thread): def __init__(self,name,delay): threading.Thread.__init__(self) self.name = name self.delay = delay def run(self): print "%s delay for %s" %(self.name,self.delay) time.sleep(self.delay) c = 0 while True: print "This is thread %s on line %s" %(self.name,c) c = c + 1 if c == 3: print "End of thread %s" % self.name break t1 = test('Thread 1', 2) t2 = test('Thread 2', 2) t1.start() print "Wait t1 to end" t1.join() t2.start() print 'End of main'
#coding=utf-8 from thread import start_new_thread import time def myfunc(a,delay): print "I will calculate square of %s after delay for %s" %(a,delay) time.sleep(delay) print "calculate begins..." result = a*a print result return result start_new_thread(myfunc,(2,5))# 同时启动两个线程 start_new_thread(myfunc,(6,8)) time.sleep(1)
主线程没有考虑子线程就退出了,可以用threading解决,如下:
import threading import time def myfunc(a,delay): print "I will calculate square of %s after delay for %s" %(a,delay) time.sleep(delay) print "calculate begins..." result = a*a print result return result t1=threading.Thread(target=myfunc,args=(2,5)) t2=threading.Thread(target=myfunc,args=(6,8)) print t1.isDaemon() print t2.isDaemon() t2.setDaemon(True) t1.start() t2.start()
建议四十七:使用Queue使多线程编程更安全
多线程从来就不是一个简单的问题,但是Queue却可以保障安全,而且不需要加锁,以生产者和消费者为例,看代码:
#!usr/bin/python #coding=utf-8 import Queue import threading import random writelock = threading.Lock() # 创建锁对象用于控制输出 class Producer(threading.Thread): def __init__(self, q,name): super(Producer, self).__init__() self.q = q self.name = name print "Producer "+self.name+" Started" def run(self): while 1: if self.q.full(): # 队列满 print 'Queue is full,producer wait!' else: value = random.randint(0,10) print self.name +" put value: " + str(value)+ "into queue" self.q.put((self.name+":"+str(value))) # 放入队列中 class Consumer(threading.Thread): # 消费者 def __init__(self, q,name): super(Consumer, self).__init__() self.q = q self.name = name print "Consumer "+self.name+" started/n " def run(self): while 1: if self.q.empty(): # 队列为空 print 'queue is empty,consumer wait!' else: value = self.q.get() # 获取一个元素 print self.name +"get value"+/ value + " from queue" if __name__ == "__main__": q = Queue.Queue(10) p = Producer(q,"P1") p.start() p1 = Producer(q,"P2") p1.start() c1 = Consumer(q,"C1") c1.start() q.join()
python中的Queue模块提供了三种队列:
参考:编写高质量代码--改善python程序的91个建议