关于多线程操作。

对于IO操作,如访问网站,写入磁盘这种需要时间等待响应的操作,多个cpu也几乎不能提高效率。

对于CPU密集型操作,如这个格式转换,可以通过多个cpu同时去进行。

但是对于python来讲,python存在GIL全局解释器的锁,导致只有一个python线程能被解释器接收。所以等于python只能对IO操作使用线程操作。

 #coding:utf8
import csv
from xml.etree.ElementTree import Element,ElementTree
import requests
from StringIO import StringIO
from test_retractxml import pretty def download(url):
#IO操作很慢,因为不能直接得到数据。如这步:是发送请求,等待数据,在等待的过程中让出CPU,自己睡眠。
response = requests.get(url,timeout=3)
if response.ok:
return StringIO(response.content) def csvToxml(scsv,fxml):
#这是CPU密集型操作,多个CPU可以同时操作
reader = csv.reader(scsv)
headers = reader.next()
headers = map(lambda h:h.replace(' ',''),headers) root = Element('Data')
for row in reader:
eRow = Element('Row')
root.append(eRow)
for tag,text in zip(headers,row):
e = Element(tag)
e.text = text
eRow.append(e) pretty(root)
et = ElementTree(root)
et.write(fxml) def handle(sid):
print 'Download ...(%d)' % sid
url = 'http://table.finance.yahoo.com/table.csv?s=%s.sz'
url %= str(sid).rjust(6,'')
rf = download(url)
if rf is None:return print 'Convert to XML...(%d)' % sid
fname = str(sid).rjust(6,'')+'.xml'
with open(fname,'wb') as wf:
csvToxml(rf, wf) from threading import Thread '''
t = Thread(target=handle,args=(1,))
t.start() print 'main thread'
'''
class MyThread(Thread):
def __init__(self,sid):
Thread.__init__(self)
self.sid = sid def run(self):
handle(self.sid) threads = []
for i in xrange(1,11):
t = MyThread(i)
threads.append(t)
t.start() for t in threads:
t.join() print 'main thread'
#t.join()#阻塞函数,保证主线程在所有子线程结束后再退出 '''
#这是串行的方法
for sid in xrange(1,11):
print 'Download ...(%d)' % sid
url = 'http://table.finance.yahoo.com/table.csv?s=%s.sz'
url %= str(sid).rjust(6,'0')
rf = download(url)
if rf is None:continue print 'Convert to XML...(%d)' % sid
fname = str(sid).rjust(6,'0')+'.xml'
with open(fname,'wb') as wf:
csvToxml(rf, wf)
'''

线程间通信,可以用全局变量,但是不够安全,可以用Queue.Queue来存储通信内容。Queue作为线程安全的队列。

 #coding:utf8
import requests
import csv
from xml.etree.ElementTree import Element,ElementTree
from test_retractxml import pretty
from threading import Thread
from StringIO import StringIO from Queue import Queue class DownloadThread(Thread): def __init__(self,sid,queue):
Thread.__init__(self)
self.sid = sid
self.url = 'http://table.finance.yahoo.com/table.csv?s=%s.sz'
self.url %=str(sid).rjust(6,'')
self.queue = queue def download(self,url):
response = requests.get(url,timeout=3)
if response.ok:
return StringIO(response.content) def run(self):
print'download',self.sid
data = self.download(self.url)
self.queue.put((self.sid,data)) class ConverThread(Thread):
def __init__(self,queue):
Thread.__init__(self)
self.queue = queue def csvToxml(self,rf,wf):
reader = csv.reader(rf)
headers = reader.next()
headers = map(lambda h:h.replace(' ',''),headers) root = Element('Data')
for row in reader:
eRow = Element('Row')
root.append(eRow)
for tag,text in zip(headers,row):
e = Element(tag)
e.text = text
eRow.append(e) pretty(root)
et = ElementTree(root)
et.write(wf) def run(self):
while True:
sid,data = self.queue.get()
print 'Convert', sid
if sid == -1:
break
if data:
fname = str(sid).rjust(6,'')+'.xml'
with open(fname,'wb') as wf:
self.csvToxml(data, wf) q = Queue()
dThreads = [DownloadThread(i,q) for i in xrange(1,11)]
cThread = ConverThread(q) for t in dThreads:#多个线程下载
t.start() cThread.start()#一个线程处理 for t in dThreads:
t.join() q.put((-1,None))

由于全局锁GIL的存在,无法用多个线程来对cpu密集操作,所以此例子中是1,用多个线程来进行IO操作;2,将所有下载的内容传给1个线程进行转换。他们之间的交换是通过存入Queue这个安全队列里面。

而进程之间的的事件通知,需要调用thread库里的Event。事件的等待是Event.wait(),事件的响应是Event.set(),需要注意的是,set之后事件就不会再wait,需要Event.clear()来重新激活wait。要把等待,响应的逻辑弄清楚。

这节还引入了守护线程setDaemon的概念,当其值为True时 ,其他线程结束时,自身也会结束。

#coding:utf8class DownloadThread(Thread):
****
class ConverThread(Thread):
def __init__(self,queue,cEvent,tEvent):
Thread.__init__(self)
self.queue = queue
self.cEvent = cEvent
self.tEvent = tEvent def csvToxml(self,rf,wf):
   **** def run(self):
count = 0
while True:
sid,data = self.queue.get()
print 'Convert', sid
if sid == -1:
self.cEvent.set()
self.tEvent.wait()
break
if data:
fname = str(sid).rjust(6,'')+'.xml'
with open(fname,'wb') as wf:
self.csvToxml(data, wf)
count += 1
if count == 5: #注意这里的逻辑
self.cEvent.set()#激活cEvent,表示转换完成 self.tEvent.wait()#等待tEvent事件完成
self.tEvent.clear()#重新激活tEevent
count = 0
import tarfile
import os class TarThread(Thread):
def __init__(self,cEvent,tEvent):
Thread.__init__(self)
self.count = 0
self.cEvent = cEvent
self.tEvent = tEvent
self.setDaemon(True)#守护线程,其他线程退出后,他也退出 def tarXML(self):
self.count += 1
tfname = '%d.tgz'%self.count
tf = tarfile.open(tfname,'w:gz')#打包命令,打包格式为gz
for fname in os.listdir('.'):#遍历当前文件夹的文件
if fname.endswith('.xml'):#找到.xml结尾的文件
tf.add(fname)#添加到压缩包中
os.remove(fname)#删除掉已添加加的文件
tf.close() if not tf.members:#如果打包文件为空,则删除
os.remove(tfname) def run(self):
while True:
self.cEvent.wait()#等待cEvent事件
self.tarXML()
self.cEvent.clear()#重新激活等待 self.tEvent.set()#激活tEvent,表示完成打包 if __name__ == '__main__':
q = Queue()
dThreads =[DownloadThread(i,q) for i in xrange(1,11)] cEvent = Event()
tEvent = Event() cThread = ConverThread(q,cEvent,tEvent)
tThread = TarThread(cEvent,tEvent)
tThread.start()#注意这里要start线程 for t in dThreads:
t.start()
cThread.start() for t in dThreads:
t.join() q.put((-1,None))
print 'main thread'

本地线程这一章开始之后都是用了python3,我暂时还是想用python2来实现,所以先放一下,以后在回来补充。

线程池:pass

多进程:pass

:pass

Python168的学习笔记7的更多相关文章

  1. Python168的学习笔记8

    #coding:utf8 #斐波那契数列,第三项起,每一项都等于前两项之和 def memo(func): cache = {}#闭包 def wrap(*args): if args not in ...

  2. Python168的学习笔记6

    如何派生内置不可变类型并修改实例化行为. 个人理解,如何派生出自己想要的类. class IntTuple(tuple): def __new__(cls,iterable): g = (x for ...

  3. Python168的学习笔记5

    关于对csv文件的操作. python标准库中有csv的库,使用非常方便. import csv with open('pingan.csv','rb') as rf: reader = csv.re ...

  4. Python168的学习笔记4

    关于普通文本文件的读写 python2.7中,未注明的字符都是以acsii来编码的,而要让字符能够通用,必须声明为unicode. s=u'你好',s.encode('utf8')就是指用utf8来进 ...

  5. Python168的学习笔记3

    list.extend(),可以拓展list,a=(0,1),b=(2,3) a.extend(b),a就变成(0,1,2,3) 分割字符串(除去字符串中的,\/;之类的),如果用str.split( ...

  6. Python168的学习笔记2

    关于for循环,其实质是利用被循环对象的__iter__,或者__getitem__属性接口,由可迭代对象得到迭代器.for循环就是不断调用.next(),直到最终捕获到stop. import re ...

  7. Python168的学习笔记1

    在对list的条件选择有两种常用方法,直接使用filter函数,就是filter(func,sequence);另外一种就是迭代操作,类似 x for x in sequence func.这两种方法 ...

  8. js学习笔记:webpack基础入门(一)

    之前听说过webpack,今天想正式的接触一下,先跟着webpack的官方用户指南走: 在这里有: 如何安装webpack 如何使用webpack 如何使用loader 如何使用webpack的开发者 ...

  9. PHP-自定义模板-学习笔记

    1.  开始 这几天,看了李炎恢老师的<PHP第二季度视频>中的“章节7:创建TPL自定义模板”,做一个学习笔记,通过绘制架构图.UML类图和思维导图,来对加深理解. 2.  整体架构图 ...

随机推荐

  1. 全网最全JS正则表达式 校验数字

    Js代码 <script type="text/javascript"> function SubmitCk() { var reg = /^([a-zA-Z0-9]+ ...

  2. Vagrant 无法校验手动下载的 Homestead Box 版本

    起因 4年前电脑,配置不太好了,现有的 Homestead 运行起来太吃内存.在修改了 Homestead.yaml 文件里 memory 选项的内存配置为 1024 后,应用最新配置重启失败. 索性 ...

  3. vue2.0组件之间的传值

    1.父子组件--props props:需要注意的是,虽然的是单向的数据流,但是如果传递的是数组或是对象这样的引用类型,子组件数据变化,父组件的数据通也会变化 子组件代码 <template&g ...

  4. 16/11/22_plsql

    1.数据类型: char 固定长度,varchar 字符长度按照实际长度, varchar2 字符均存储2个字节, nvarchar 按照Unicode存储.number(m,n)总长度m,小数 n. ...

  5. DevExpress 去除皮肤的方法

    我从不用皮肤,方法如下:

  6. java -D 参数功能解析

    我们都知道在启动tomcat或直接执行java命令的时候可以通过参数-XX等来配置虚拟机的大小,同样,也应该留意到java -Dkey=value的参数.那么这个参数是什么作用呢? 使用案例 其实,在 ...

  7. VS Code折腾记 - (3) 多图解VSCode基础功能

    前言 想了想,对于一个刚接触VSCODE的人来说,有什么比图片更通俗易懂的呢? 启动界面 : 快捷键(Ctrl + Shift + E) Search && replace : 快捷键 ...

  8. 根据后端传的时间前端js进行倒计时

    一.故事背景: 1. 今天公司有个项目需求 2. 在前端页面实现一个倒计时功能 3. 初步设想:后端根据需求规定一个未来的时间,前端根据当前时间进行计算 4. 然后将时间格式化,时分秒的格式 5. 时 ...

  9. Oracle学习笔记:parallel并行处理

    在使用oracel查询时,可以通过并行提高查询速度.例如: ) from table_name a; 强行启用并行度来执行当前SQL.加上这个说明之后,可以强行启用Oracle的多线程处理功能,提高效 ...

  10. python开发学习-day16(Django框架初识)

    s12-20160507-day16 *:first-child { margin-top: 0 !important; } body>*:last-child { margin-bottom: ...