原文发表在我的博客主页,转载请注明出处!
建议四十一:一般情况下使用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个建议