Python168的学习笔记7
关于多线程操作。
对于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的更多相关文章
- Python168的学习笔记8
#coding:utf8 #斐波那契数列,第三项起,每一项都等于前两项之和 def memo(func): cache = {}#闭包 def wrap(*args): if args not in ...
- Python168的学习笔记6
如何派生内置不可变类型并修改实例化行为. 个人理解,如何派生出自己想要的类. class IntTuple(tuple): def __new__(cls,iterable): g = (x for ...
- Python168的学习笔记5
关于对csv文件的操作. python标准库中有csv的库,使用非常方便. import csv with open('pingan.csv','rb') as rf: reader = csv.re ...
- Python168的学习笔记4
关于普通文本文件的读写 python2.7中,未注明的字符都是以acsii来编码的,而要让字符能够通用,必须声明为unicode. s=u'你好',s.encode('utf8')就是指用utf8来进 ...
- Python168的学习笔记3
list.extend(),可以拓展list,a=(0,1),b=(2,3) a.extend(b),a就变成(0,1,2,3) 分割字符串(除去字符串中的,\/;之类的),如果用str.split( ...
- Python168的学习笔记2
关于for循环,其实质是利用被循环对象的__iter__,或者__getitem__属性接口,由可迭代对象得到迭代器.for循环就是不断调用.next(),直到最终捕获到stop. import re ...
- Python168的学习笔记1
在对list的条件选择有两种常用方法,直接使用filter函数,就是filter(func,sequence);另外一种就是迭代操作,类似 x for x in sequence func.这两种方法 ...
- js学习笔记:webpack基础入门(一)
之前听说过webpack,今天想正式的接触一下,先跟着webpack的官方用户指南走: 在这里有: 如何安装webpack 如何使用webpack 如何使用loader 如何使用webpack的开发者 ...
- PHP-自定义模板-学习笔记
1. 开始 这几天,看了李炎恢老师的<PHP第二季度视频>中的“章节7:创建TPL自定义模板”,做一个学习笔记,通过绘制架构图.UML类图和思维导图,来对加深理解. 2. 整体架构图 ...
随机推荐
- gnuplot生成MySQL QPS图形
1.建立MySQL QPS执行脚本 #!/bin/bash mysqladmin -uroot -p' extended-status -i1|awk \ 'BEGIN{flag=0; print & ...
- Java集合Map与其子类回顾
接10月12号昨天的笔记,今天继续回顾集合中的Map集合. 一.集合工具操作类Collections 问题:collection和collections的区别? 1.collection是单列集合的顶 ...
- 数据结构之 栈 (Python 版)
数据结构之 栈 (Python 版) -- 利用线性表实现栈 栈的特性: 后进先出 基于顺序表实现栈 class SStack(): ''' 基于顺序表 实现的 栈类 ''' def __init__ ...
- 你真的了解js伪数组吗?深入js伪数组
关于js伪数组 具有length属性: 按索引方式存储数据: 不具有数组的push().pop()等方法: 你可能知道怎么把伪数组转换为数组,但是你知道这里边的原理吗? 假如页面有一组li元素 < ...
- KVM virsh常用命令篇
1.查看运行的虚拟机 virsh list 2.查看所有的虚拟机(关闭和运行的虚拟机) virsh list --all 3.连接虚拟机 virsh console +域名(虚拟机的名称) 4.退出虚 ...
- ioctl()函数获取本机IP、MAC
#include <sys/ioctl.h> int ioctl(int d, int request, ...); /* Socket configuration controls. * ...
- Linux基础入门学习笔记之三
第四节 Linux目录结构及文件基本操作 Linux目录结构 Linux 的目录与 Windows 的目录的区别 目录与存储介质(磁盘,内存,DVD 等)的关系 Windows 一直是==以存储介质为 ...
- ld 脚本浅析-LD手册粗糙翻译
本文乃转载, 我在其基础上做了少量修改. 原作者的E-mail是zhanglei@sict.ac.cn. 完成于2005.11.5-2005.11.8 0. Contents 1. 概论2. 基本概念 ...
- PHP性能调优---php-fpm中启用慢日志配置(用于检测执行较慢的PHP脚本)
虽然通过nginx accesslog可以记录用户访问某个接口或者网页所消耗的时间,但是不能清晰地追踪到具体哪个位置或者说函数慢,所以通过php-fpm慢日志,slowlog设置可以让我们很好的看见哪 ...
- 从字节码角度分析Byte类型变量b++和++b
1. 下面是一到Java笔试题: public class Test2 { public void add(Byte b) { b = b++; } public void test() { Byte ...