多线程类似于同时实行多个不同程序,多线程运行有如下优点:
利用线程可以把霸占永劫光的程序中的任务放到后台去处理。
用户界面可以更加吸引人,这样比如用户点击了一个按钮去触发某些事宜的处理,可以弹出一个进度条来显示处理的进度

程序的运行速率可能加快
在一些等待的任务实现上如用户输入、文件读写和网络收发数据等,线程就比较有用了。在这种情形下我们可以开释一些宝贵的资源如内存占用等等。
线程在实行过程中与进程还是有差异的。每个独立的线程有一个程序运行的入口、顺序实行序列和程序的出口。但是线程不能够独立实行,必须依存在运用程序中,由运用程序供应多个线程实行掌握。
每个线程都有他自己的一组CPU寄存器,称为线程的高下文,该高下文反响了线程上次运行该线程的CPU寄存器的状态。
指令指针和堆栈指针寄存器是线程高下文中两个最主要的寄存器,线程总是在进程得到高下文中运行的,这些地址都用于标志拥有线程的进程地址空间中的内存。
线程可以被抢占(中断)。
在其他线程正在运行时,线程可以暂时搁置(也称为就寝) -- 这便是线程的妥协。
开始学习Python线程
Python中利用线程有两种办法:函数或者用类来包装线程工具。
函数式:调用thread模块中的start_new_thread()函数来产生新线程。语法如下:
thread.start_new_thread ( function, args[, kwargs] )
参数解释:
function - 线程函数。
args - 通报给线程函数的参数,他必须是个tuple类型。
kwargs - 可选参数。
实例(Python 2.0+)
#!/usr/bin/python# -- coding: UTF-8 --importthreadimporttime# 为线程定义一个函数defprint_time(threadName, delay): count = 0whilecount < 5: time.sleep(delay)count += 1print\公众%s: %s\公众 % (threadName, time.ctime(time.time()))# 创建两个线程try: thread.start_new_thread(print_time, (\"大众Thread-1\"大众, 2, ))thread.start_new_thread(print_time, (\"大众Thread-2\公众, 4, ))except: print\"大众Error: unable to start thread\公众while1: pass
实行以上程序输出结果如下:
Thread-1: Thu Jan 22 15:42:17 2009Thread-1: Thu Jan 22 15:42:19 2009Thread-2: Thu Jan 22 15:42:19 2009Thread-1: Thu Jan 22 15:42:21 2009Thread-2: Thu Jan 22 15:42:23 2009Thread-1: Thu Jan 22 15:42:23 2009Thread-1: Thu Jan 22 15:42:25 2009Thread-2: Thu Jan 22 15:42:27 2009Thread-2: Thu Jan 22 15:42:31 2009Thread-2: Thu Jan 22 15:42:35 2009
线程的结束一样平常依赖线程函数的自然结束;也可以在线程函数中调用thread.exit(),他抛出SystemExit exception,达到退出线程的目的。
线程模块
Python通过两个标准库thread和threading供应对线程的支持。thread供应了低级别的、原始的线程以及一个大略的锁。
thread 模块供应的其他方法:
threading.currentThread(): 返回当前的线程变量。
threading.enumerate(): 返回一个包含正在运行的线程的list。正在运行指线程启动后、结束前,不包括启动前和终止后的线程。
threading.activeCount(): 返回正在运行的线程数量,与len(threading.enumerate())有相同的结果。
除了利用方法外,线程模块同样供应了Thread类来处理线程,Thread类供应了以下方法:
run(): 用以表示线程活动的方法。
start():启动线程活动。
join([time]): 等待至线程中止。这壅塞调用线程直至线程的join() 方法被调用中止-正常退出或者抛出未处理的非常-或者是可选的超时发生。
isAlive(): 返回线程是否活动的。
getName(): 返回线程名。
setName(): 设置线程名。
利用Threading模块创建线程
利用Threading模块创建线程,直接从threading.Thread继续,然后重写__init__方法和run方法:
实例(Python 2.0+)
#!/usr/bin/python# -- coding: UTF-8 --importthreadingimporttimeexitFlag = 0classmyThread(threading.Thread): #继续父类threading.Threaddef__init__(self, threadID, name, counter): threading.Thread.__init__(self)self.threadID = threadIDself.name = nameself.counter = counterdefrun(self): #把要实行的代码写到run函数里面 线程在创建后会直接运行run函数 print\"大众Starting \"大众 + self.nameprint_time(self.name, self.counter, 5)print\"大众Exiting \公众 + self.namedefprint_time(threadName, delay, counter): whilecounter: ifexitFlag: threading.Thread.exit()time.sleep(delay)print\"大众%s: %s\公众 % (threadName, time.ctime(time.time()))counter -= 1# 创建新线程thread1 = myThread(1, \"大众Thread-1\公众, 1)thread2 = myThread(2, \"大众Thread-2\"大众, 2)# 开启线程thread1.start()thread2.start()print\"大众Exiting Main Thread\"大众
以上程序实行结果如下;
Starting Thread-1Starting Thread-2Exiting Main ThreadThread-1: Thu Mar 21 09:10:03 2013Thread-1: Thu Mar 21 09:10:04 2013Thread-2: Thu Mar 21 09:10:04 2013Thread-1: Thu Mar 21 09:10:05 2013Thread-1: Thu Mar 21 09:10:06 2013Thread-2: Thu Mar 21 09:10:06 2013Thread-1: Thu Mar 21 09:10:07 2013Exiting Thread-1Thread-2: Thu Mar 21 09:10:08 2013Thread-2: Thu Mar 21 09:10:10 2013Thread-2: Thu Mar 21 09:10:12 2013Exiting Thread-2
线程同步
如果多个线程共同对某个数据修正,则可能涌现不可预见的结果,为了担保数据的精确性,须要对多个线程进行同步。
利用Thread工具的Lock和Rlock可以实现大略的线程同步,这两个工具都有acquire方法和release方法,对付那些须要每次只许可一个线程操作的数据,可以将其操作放到acquire和release方法之间。如下:
多线程的上风在于可以同时运行多个任务(至少觉得起来是这样)。但是当线程须要共享数据时,可能存在数据不同步的问题。
考虑这样一种情形:一个列表里所有元素都是0,线程\"大众set\"大众从后向前把所有元素改成1,而线程\公众print\公众卖力从前今后读取列表并打印。
那么,可能线程\公众set\"大众开始改的时候,线程\"大众print\公众便来打印列表了,输出就成了一半0一半1,这便是数据的不同步。为了避免这种情形,引入了锁的观点。
锁有两种状态——锁定和未锁定。每当一个线程比如\公众set\"大众要访问共享数据时,必须先得到锁定;如果已经有别的线程比如\公众print\"大众得到锁定了,那么就让线程\公众set\"大众停息,也便是同步壅塞;等到线程\"大众print\"大众访问完毕,开释锁往后,再让线程\公众set\"大众连续。
经由这样的处理,打印列表时要么全部输出0,要么全部输出1,不会再涌现一半0一半1的尴尬场面。
实例(Python 2.0+)
#!/usr/bin/python# -- coding: UTF-8 --importthreadingimporttimeclassmyThread(threading.Thread): def__init__(self, threadID, name, counter): threading.Thread.__init__(self)self.threadID = threadIDself.name = nameself.counter = counterdefrun(self): print\公众Starting \公众 + self.name# 得到锁,成功得到锁定后返回True# 可选的timeout参数不填时将一贯壅塞直到得到锁定# 否则超时后将返回FalsethreadLock.acquire()print_time(self.name, self.counter, 3)# 开释锁threadLock.release()defprint_time(threadName, delay, counter): whilecounter: time.sleep(delay)print\"大众%s: %s\"大众 % (threadName, time.ctime(time.time()))counter -= 1threadLock = threading.Lock()threads = []# 创建新线程thread1 = myThread(1, \公众Thread-1\公众, 1)thread2 = myThread(2, \"大众Thread-2\公众, 2)# 开启新线程thread1.start()thread2.start()# 添加线程到线程列表threads.append(thread1)threads.append(thread2)# 等待所有线程完成fortinthreads: t.join()print\公众Exiting Main Thread\公众
线程优先级行列步队( Queue)
Python的Queue模块中供应了同步的、线程安全的行列步队类,包括FIFO(先入先出)行列步队Queue,LIFO(后入先出)行列步队LifoQueue,和优先级行列步队PriorityQueue。这些行列步队都实现了锁原语,能够在多线程中直策应用。可以利用行列步队来实现线程间的同步。
Queue模块中的常用方法:
Queue.qsize() 返回行列步队的大小
Queue.empty() 如果行列步队为空,返回True,反之False
Queue.full() 如果行列步队满了,返回True,反之False
Queue.full 与 maxsize 大小对应
Queue.get([block[, timeout]])获取行列步队,timeout等待韶光
Queue.get_nowait() 相称Queue.get(False)
Queue.put(item) 写入行列步队,timeout等待韶光
Queue.put_nowait(item) 相称Queue.put(item, False)
Queue.task_done() 在完成一项事情之后,Queue.task_done()函数向任务已经完成的行列步队发送一个旗子暗记
Queue.join() 实际上意味着等到行列步队为空,再实行别的操作
实例(Python 2.0+)
#!/usr/bin/python# -- coding: UTF-8 --importQueueimportthreadingimporttimeexitFlag = 0classmyThread(threading.Thread): def__init__(self, threadID, name, q): threading.Thread.__init__(self)self.threadID = threadIDself.name = nameself.q = qdefrun(self): print\"大众Starting \"大众 + self.nameprocess_data(self.name, self.q)print\公众Exiting \"大众 + self.namedefprocess_data(threadName, q): whilenotexitFlag: queueLock.acquire()ifnotworkQueue.empty(): data = q.get()queueLock.release()print\"大众%s processing %s\"大众 % (threadName, data)else: queueLock.release()time.sleep(1)threadList = [\"大众Thread-1\"大众, \"大众Thread-2\"大众, \"大众Thread-3\公众]nameList = [\公众One\"大众, \"大众Two\"大众, \公众Three\"大众, \"大众Four\"大众, \"大众Five\"大众]queueLock = threading.Lock()workQueue = Queue.Queue(10)threads = []threadID = 1# 创建新线程fortNameinthreadList: thread = myThread(threadID, tName, workQueue)thread.start()threads.append(thread)threadID += 1# 添补行列步队queueLock.acquire()forwordinnameList: workQueue.put(word)queueLock.release()# 等待行列步队清空whilenotworkQueue.empty(): pass# 关照线程是时候退出exitFlag = 1# 等待所有线程完成fortinthreads: t.join()print\"大众Exiting Main Thread\"大众
以上程序实行结果:
Starting Thread-1Starting Thread-2Starting Thread-3Thread-1 processing OneThread-2 processing TwoThread-3 processing ThreeThread-1 processing FourThread-2 processing FiveExiting Thread-3Exiting Thread-1Exiting Thread-2Exiting Main ThreadPython XML解析
什么是XML?
XML 指可扩展标记措辞(eXtensible Markup Language)。 你可以通过本站学习XML教程
XML 被设计用来传输和存储数据。
XML是一套定义语义标记的规则,这些标记将文档分成许多部件并对这些部件加以标识。
它也是元标记措辞,即定义了用于定义其他与特定领域有关的、语义的、构造化的标记措辞的句法措辞。
python对XML的解析
常见的XML编程接口有DOM和SAX,这两种接口处理XML文件的办法不同,当然利用场合也不同。
python有三种方法解析XML,SAX,DOM,以及ElementTree:
1.SAX (simple API for XML )
python 标准库包含SAX解析器,SAX用事宜驱动模型,通过在解析XML的过程中触发一个个的事宜并调用用户定义的回调函数来处理XML文件。
2.DOM(Document Object Model)
将XML数据在内存中解析成一个树,通过对树的操作来操作XML。
3.ElementTree(元素树)
ElementTree就像一个轻量级的DOM,具有方便友好的API。代码可用性好,速率快,花费内存少。
注:因DOM须要将XML数据映射到内存中的树,一是比较慢,二是比较耗内存,而SAX流式读取XML文件,比较快,占用内存少,但须要用户实现回调函数(handler)。
本章节利用到的XML实例文件movies.xml内容如下:
<collection shelf=\"大众New Arrivals\"大众><movie title=\"大众Enemy Behind\"大众> <type>War, Thriller</type> <format>DVD</format> <year>2003</year> <rating>PG</rating> <stars>10</stars> <description>Talk about a US-Japan war</description></movie><movie title=\"大众Transformers\公众> <type>Anime, Science Fiction</type> <format>DVD</format> <year>1989</year> <rating>R</rating> <stars>8</stars> <description>A schientific fiction</description></movie> <movie title=\公众Trigun\"大众> <type>Anime, Action</type> <format>DVD</format> <episodes>4</episodes> <rating>PG</rating> <stars>10</stars> <description>Vash the Stampede!</description></movie><movie title=\"大众Ishtar\公众> <type>Comedy</type> <format>VHS</format> <rating>PG</rating> <stars>2</stars> <description>Viewable boredom</description></movie></collection>
python利用SAX解析xml
SAX是一种基于事宜驱动的API。
利用SAX解析XML文档牵扯到两个部分:解析器和事宜处理器。
解析器卖力读取XML文档,并向事宜处理器发送事宜,如元素开始跟元素结束事宜;
而事宜处理器则卖力对事宜作出相应,对通报的XML数据进行处理。
<psax适于处理下面的问题:< p=\公众\"大众 style=\公众color: rgb(51, 51, 51); font-family: \"大众Helvetica Neue\"大众, Helvetica, \公众PingFang SC\"大众, \"大众Hiragino Sans GB\"大众, \公众Microsoft YaHei\"大众, \"大众Noto Sans CJK SC\"大众, \"大众WenQuanYi Micro Hei\"大众, Arial, sans-serif; font-size: 12px; white-space: normal;\"大众>
1、对大型文件进行处理;
2、只须要文件的部分内容,或者只需从文件中得到特定信息。
3、想建立自己的工具模型的时候。
在python中利用sax办法处理xml要先引入xml.sax中的parse函数,还有xml.sax.handler中的ContentHandler。
ContentHandler类方法先容
characters(content)方法
调用机遇:
从行开始,碰着标签之前,存在字符,content的值为这些字符串。
从一个标签,碰着下一个标签之前, 存在字符,content的值为这些字符串。
从一个标签,碰着行结束符之前,存在字符,content的值为这些字符串。
标签可以是开始标签,也可以是结束标签。
startDocument()方法
文档启动的时候调用。
endDocument()方法
解析器到达文档结尾时调用。
startElement(name, attrs)方法
碰着XML开始标签时调用,name是标签的名字,attrs是标签的属性值字典。
endElement(name)方法
碰着XML结束标签时调用。
make_parser方法
以下方法创建一个新的解析器工具并返回。
xml.sax.make_parser( [parser_list] )
参数解释:
parser_list - 可选参数,解析器列表
parser方法
以下方法创建一个 SAX 解析器并解析xml文档:
xml.sax.parse( xmlfile, contenthandler[, errorhandler])
参数解释:
xmlfile - xml文件名
contenthandler - 必须是一个ContentHandler的工具
errorhandler - 如果指定该参数,errorhandler必须是一个SAX ErrorHandler工具
parseString方法
parseString方法创建一个XML解析器并解析xml字符串:
xml.sax.parseString(xmlstring, contenthandler[, errorhandler])
参数解释:
xmlstring - xml字符串
contenthandler - 必须是一个ContentHandler的工具
errorhandler - 如果指定该参数,errorhandler必须是一个SAX ErrorHandler工具
Python 解析XML实例#!/usr/bin/python# -- coding: UTF-8 --import xml.saxclass MovieHandler( xml.sax.ContentHandler ): def __init__(self): self.CurrentData = \"大众\"大众 self.type = \"大众\"大众 self.format = \"大众\"大众 self.year = \"大众\"大众 self.rating = \公众\"大众 self.stars = \公众\"大众 self.description = \公众\"大众 # 元素开始事宜处理 def startElement(self, tag, attributes): self.CurrentData = tag if tag == \"大众movie\"大众: print \公众Movie\"大众 title = attributes[\"大众title\"大众] print \"大众Title:\"大众, title # 元素结束事宜处理 def endElement(self, tag): if self.CurrentData == \"大众type\"大众: print \"大众Type:\"大众, self.type elif self.CurrentData == \公众format\"大众: print \"大众Format:\"大众, self.format elif self.CurrentData == \公众year\"大众: print \"大众Year:\"大众, self.year elif self.CurrentData == \"大众rating\公众: print \"大众Rating:\"大众, self.rating elif self.CurrentData == \"大众stars\公众: print \公众Stars:\公众, self.stars elif self.CurrentData == \公众description\公众: print \"大众Description:\"大众, self.description self.CurrentData = \"大众\"大众 # 内容事宜处理 def characters(self, content): if self.CurrentData == \"大众type\"大众: self.type = content elif self.CurrentData == \"大众format\"大众: self.format = content elif self.CurrentData == \"大众year\"大众: self.year = content elif self.CurrentData == \公众rating\"大众: self.rating = content elif self.CurrentData == \公众stars\"大众: self.stars = content elif self.CurrentData == \"大众description\"大众: self.description = content if ( __name__ == \公众__main__\"大众): # 创建一个 XMLReader parser = xml.sax.make_parser() # turn off namepsaces parser.setFeature(xml.sax.handler.feature_namespaces, 0) # 重写 ContextHandler Handler = MovieHandler() parser.setContentHandler( Handler ) parser.parse(\"大众movies.xml\公众)
以上代码实行结果如下:
MovieTitle: Enemy BehindType: War, ThrillerFormat: DVDYear: 2003Rating: PGStars: 10Description: Talk about a US-Japan warMovieTitle: TransformersType: Anime, Science FictionFormat: DVDYear: 1989Rating: RStars: 8Description: A schientific fictionMovieTitle: TrigunType: Anime, ActionFormat: DVDRating: PGStars: 10Description: Vash the Stampede!MovieTitle: IshtarType: ComedyFormat: VHSRating: PGStars: 2Description: Viewable boredom
完全的 SAX API 文档请查阅Python SAX APIs
利用xml.dom解析xml
文件工具模型(Document Object Model,简称DOM),是W3C组织推举的处理可扩展置标语言的标准编程接口。
一个 DOM 的解析器在解析一个 XML 文档时,一次性读取全体文档,把文档中所有元素保存在内存中的一个树构造里,之后你可以利用DOM 供应的不同的函数来读取或修正文档的内容和构造,也可以把修正过的内容写入xml文件。
python中用xml.dom.minidom来解析xml文件,实例如下:
#!/usr/bin/python# -- coding: UTF-8 --from xml.dom.minidom import parseimport xml.dom.minidom# 利用minidom解析器打开 XML 文档DOMTree = xml.dom.minidom.parse(\"大众movies.xml\"大众)collection = DOMTree.documentElementif collection.hasAttribute(\"大众shelf\"大众): print \"大众Root element : %s\公众 % collection.getAttribute(\"大众shelf\"大众)# 在凑集中获取所有电影movies = collection.getElementsByTagName(\公众movie\公众)# 打印每部电影的详细信息for movie in movies: print \公众Movie\"大众 if movie.hasAttribute(\"大众title\"大众): print \公众Title: %s\"大众 % movie.getAttribute(\"大众title\"大众) type = movie.getElementsByTagName('type')[0] print \"大众Type: %s\"大众 % type.childNodes[0].data format = movie.getElementsByTagName('format')[0] print \"大众Format: %s\公众 % format.childNodes[0].data rating = movie.getElementsByTagName('rating')[0] print \"大众Rating: %s\公众 % rating.childNodes[0].data description = movie.getElementsByTagName('description')[0] print \"大众Description: %s\"大众 % description.childNodes[0].data
以上程序实行结果如下:
Root element : New ArrivalsMovieTitle: Enemy BehindType: War, ThrillerFormat: DVDRating: PGDescription: Talk about a US-Japan warMovieTitle: TransformersType: Anime, Science FictionFormat: DVDRating: RDescription: A schientific fictionMovieTitle: TrigunType: Anime, ActionFormat: DVDRating: PGDescription: Vash the Stampede!MovieTitle: IshtarType: ComedyFormat: VHSRating: PG
Description: Viewable boredom
Python 供应了多个图形开拓界面的库,几个常用 Python GUI 库如下:
Tkinter: Tkinter 模块(Tk 接口)是 Python 的标准 Tk GUI 工具包的接口 .Tk 和 Tkinter 可以在大多数的 Unix 平台下利用,同样可以运用在 Windows 和 Macintosh 系统里。Tk8.0 的后续版本可以实现本地窗口风格,并良好地运行在绝大多数平台中。
wxPython:wxPython 是一款开源软件,是 Python 措辞的一套精良的 GUI 图形库,许可 Python 程序员很方便的创建完全的、功能键全的 GUI 用户界面。
Jython:Jython 程序可以和 Java 无缝集成。除了一些标准模块,Jython 利用 Java 的模块。Jython 险些拥有标准的Python 中不依赖于 C 措辞的全部模块。比如,Jython 的用户界面将利用 Swing,AWT或者 SWT。Jython 可以被动态或静态地编译成 Java 字节码。
Tkinter 编程
Tkinter 是 Python 的标准 GUI 库。Python 利用 Tkinter 可以快速的创建 GUI 运用程序。
由于 Tkinter 是内置到 python 的安装包中、只要安装好 Python 之后就能 import Tkinter 库、而且 IDLE 也是用 Tkinter 编写而成、对付大略的图形界面 Tkinter 还是能搪塞自若。
把稳:Python3.x 版本利用的库名为 tkinter,即首写字母 T 为小写。
import tkinter
创建一个GUI程序
1、导入 Tkinter 模块
2、创建控件
3、指定这个控件的 master, 即这个控件属于哪一个
4、见告 GM(geometry manager) 有一个控件产生了。
实例:
#!/usr/bin/python# -- coding: UTF-8 --import Tkintertop = Tkinter.Tk()# 进入循环top.mainloop()
以上代码实行结果如下图:
实例2:
#!/usr/bin/python# -- coding: UTF-8 --from Tkinter import # 导入 Tkinter 库root = Tk() # 创建窗口工具的背景色 # 创建两个列表li = ['C','python','php','html','SQL','java']movie = ['CSS','jQuery','Bootstrap']listb = Listbox(root) # 创建两个列表组件listb2 = Listbox(root)for item in li: # 第一个小部件插入数据 listb.insert(0,item)for item in movie: # 第二个小部件插入数据 listb2.insert(0,item)listb.pack() # 将小部件放置到主窗口中listb2.pack()root.mainloop() # 进入循环
以上代码实行结果如下图:
Tkinter 组件
Tkinter的供应各种控件,如按钮,标签和文本框,一个GUI运用程序中利用。这些控件常日被称为控件或者部件。
目前有15种Tkinter的部件。我们提出这些部件以及一个简短的先容,不才面的表:
标准属性
标准属性也便是所有控件的共同属性,如大小,字体和颜色等等。
属性描述Dimension控件大小;Color控件颜色;Font控件字体;Anchor锚点;Relief控件样式;Bitmap位图;Cursor光标;几何管理
Tkinter控件有特定的几何状态管理方法,管理全体控件区域组织,一下是Tkinter公开的几何管理类:包、网格、位置
几何方法描述pack()包装;grid()网格;place()位置;