一、XML文件的读取
练习
DVD管理系统的解析
1.利用ElementTree来解析dvd管理系统信息
输入一个dvd管理代码文件
#usr/bin/puthon
#-*-coding:utf-8-*-
from 基础 import dvd_read as dr
class DVD:
def __init__(self):
self.name = ""
self.price = ""
self.state = ""
# if len(args)>0:
# self.name=args[0]
# self.price=args[1]
# self.state=args[3]
if '__main__'==__name__:
# xiyouji=DVD('西游记',100,0)#0代表未借出 1 代表已借出
# sanguo=DVD('三国',100,1)
# shuihuzhuan=DVD('水浒传',100,0)
# dvds={xiyouji.name:xiyouji,sanguo.name:sanguo,shuihuzhuan.name:shuihuzhuan}
dvds=dr.getdvds()
while True:
print('1.查询所有DVD')
print('2.增加DVD')
print('3.借出DVD')
print('4.归还DVD')
print('5.退出')
num=int(input('请输入数字:'))
if num==1:
print('名称\t价格\t状态')
for key in dvds.keys():
if dvds.get(key).state.__eq__('0'):
print(key+' \t'+str(dvds.get(key).price)+' \t'+'未借出')
else:
print(key+' \t'+str(dvds.get(key).price)+' \t'+'已借出')
elif num==2:
name=input('请输入新的DVD:')
while name in dvds.keys():
name=input('此DVD已存在 请重新输入名字:')
price=int(input('请输入新DVD价格:'))
new_dvd=DVD()
new_dvd.name=name
new_dvd.price=price
new_dvd.state=0
dvds[name]=new_dvd
print('增加成功')
elif num==3:
name = input('请输入你所需要的DVD:')
while name not in dvds.keys():
name=input('此DVD不存在 请重新输入名字:')
if dvds.get(name).state==1:
print(name,'已借出')
else:
dvds.get(name).state=1
print('借出成功')
elif num==4:
name = input('请输入你所归还的DVD:')
while name not in dvds.keys():
name=input('此DVD不存在,请重新输入DVD名字')
if dvds.get(name).state==0:
print('此DVD未借出')
else:
dvds.get(name).state=0
date=int(input('请输入借书日期'))
print('扫一扫付款',int(date*int(dvds.get(name).price)),'元')
print('归还成功')
elif num==5:
print('欢迎使用')
break
输入一个dvd.xml文件
<?xml version="1.0" encoding="UTF-8" ?>
<dvds>
<dvd>
<name>西游记</name>
<price>200</price>
<state>1</state>#0代表未借出 1代表已借出
</dvd>
<dvd>
<name>水浒传</name>
<price>250</price>
<state>0</state>
</dvd>
<dvd>
<name>三国</name>
<price>300</price>
<state>1</state>
</dvd>
</dvds>
通过ElementTree解析xml文件
import xml.etree.ElementTree as ET
from 基础.DVD import DVD
tree=ET.parse('dvd.xml')
root=tree.getroot()
dvds={}
def getdvds():
for dvd in root:
n_dvd = DVD()
for ele in dvd:
if ele.tag=='name':
n_dvd.name=ele.text
elif ele.tag=='price':
n_dvd.price=ele.text
elif ele.tag=='state':
n_dvd.state=ele.text
dvds[n_dvd.name]=n_dvd
return dvds
2.利用sax解析器来处理dvd管理系统信息
通过sax来解析xml文件
import xml.sax
class dvdHandler(xml.sax.ContentHandler):
def __init__(self):
self.CurrentData = ""
self.name = ""
self.price = ""
self.state = ""
def startElement(self, tag, attributes):
self.CurrentData = tag
def endElement(self, tag):
if self.CurrentData == "name":
print ("name:", self.name)
elif self.CurrentData == "price":
print ("price:", self.price)
elif self.CurrentData == "state":
print ("state:", self.state)
self.CurrentData = ""
def characters(self, content):#
if self.CurrentData == "name":
self.name = content
elif self.CurrentData == "price":
self.price = content
elif self.CurrentData == "state":
self.state = content
if ( __name__ == "__main__"):
parser = xml.sax.make_parser()
parser.setFeature(xml.sax.handler.feature_namespaces, 0)
Handler = dvdHandler()
parser.setContentHandler( Handler )
parser.parse("dvd.xml")
执行命令得
name: 西游记
price: 200
state: 1
name: 水浒传
price: 250
state: 0
name: 三国
price: 300
state: 1
二、CSV文件
Python处理csv文件
CSV(Comma-Separated Values)及逗号隔开值,可以用Excek打开查看.由于是纯文本,任何编辑器也都可打开.与Excel文件不同,CSV文件中:
<1>值没有类型,所有值都是字符串
<2>不能指定字体颜色等样式
<3>不能指定单元格的宽高,不能合并单元格
<4>没有多个工作表
<5>不能嵌入图像图表
在CSV文件中,以(,)作为分隔符,分割两个单元格.像这样a,,c表示单元格a和单元格c之间有个空白格.以此类推,不是每个逗号都表示单元格之间的分界.所以即使CSV是纯文本文件,也坚持使用专门的模块进行处理.Python内置了CSV模块
我们常常需要读取和处理CSV文件的数据.处理CSV数据的一个最常用的方法就是把它转换为一个字典列表
DictReader类将会自动的使用CSV文件的第一行作为字典的key属性名.DictReader类返回一个将会遍历csv文件所有行的对象.
这个文件对象通过open()函数产生.我们提供了open()两个函数第一个是csv文件名,第二个是模式.在这个例子中,'rU'有两个意思,'r'表示只读模式打开文件.'U'表示我们将会接受通用换行符:'\n' '\r' '\r\n'(注:\n: 回车,光标在下一行 \r:换行,光标在上一行 \r\n回车加换行)
例:
准备一个csv文件
1,2,3,4,5
a,b,c,d,e
11,22,33,44,55
读取csv文件
import csv
#调用csv文件的读取方法csv.DictReader()
Dict=csv.DictReader(open('文件.csv','rU'))#可迭代
print(type(Dict))
print(Dict)
print([x for x in Dict])
执行命令得
<class 'csv.DictReader'>
<csv.DictReader object at 0x057902B0>
[OrderedDict([('1', 'a'), ('2', 'b'), ('3', 'c'), ('4', 'd'), ('5', 'e')]), OrderedDict([('1', '11'), ('2', '22'), ('3', '33'), ('4', '44'), ('5', '55')])]
当需要读取key或者values时
import csv
Dict=csv.DictReader(open('文件.csv','rU'))#可迭代
print([d.keys() for d in Dict])
# print([c.values() for c in Dict])
执行命令得
[odict_keys(['1', '2', '3', '4', '5']), odict_keys(['1', '2', '3', '4', '5'])]
#[odict_values(['a', 'b', 'c', 'd', 'e']), odict_values(['11', '22', '33', '44', '55'])]
三、进程和线程
1.概念
进程是什么?线程是什么?二者之间有什么区别和联系?
<1>进程是资源分配的基本单位
<2>线程是CPU独立运行和独立调度的基本单位
两者的联系:进程和线程都是操作系统所运行的程序运行的基本单位
区别:
<1>进程具有独立的空间地址,一个进程崩溃后,在保护模式下不会对其他进程产生影响
<2>线程是一个进程的不同执行路径.线程有自己的堆栈和全局变量,但线程之间没有单独的地址空间,一个线程死掉就等于整个进程死掉
多进程的程序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差些,对于一些要求同时进行并且有要共享某些变量的并发操作,只能用线程,不能用进程
什么是多线程?
多线程:是指从软件或者硬件上实现多个线程的并发技术,如在一个进程中同时运行了多个线程,用来完成不同的工作,则称之为'多线程,多个线程交替占用CPU资源,而非真正的并行执行'
多线程的好处:
<1>使用多线程可以把程序中占据时间长的任务放到后台去处理,如图片视频的下载
<2>发挥多核处理器的优势,并发执行让系统运行的更快更顺畅用户体验好
多线程的缺点:
<1>大量的线程降低代码的可读性
<2>更多的线程需要更多的储存空间
<3>当多个线程对同一个资源出现争夺时候要注意县城的安全问题
进程的特点:独立(内存独立,CPU使用独立)启动进程开销大(速率低),进程之间很难共享数据,和数据通信, 但数据安全性高.
线程的特点:依赖进程(内存共享,CPU使用独立)启动开销小,进程之间共享数据容易,方便通信,不安全
2.开始学习Python线程
调用:
Python2:thread
Python3:_thread
threading(功能比_thread更强大,推荐使用)
2.线程模块
Python通过两个标准库thread和threading提供对线程的支持,thread提供了低级别的,原始的线程以及一个简单的锁
threading模块提供的其他方法
方法 | 描述 |
threading.currentThread() | 返回当前的线程变量 |
threading.enumerate() | 返回一个包含正在运行的线程的list.正在运行指线程启动后,结束前,不包括启动前和终止后的线程 |
threading.activeCount() | 返回正在运行的线程数量,与len(threading.enumerate())有相同的结果. |
import threading
print([x for x in range(9)])#创建一个线程
thread=threading.current_thread()#返回获取当前线程变量
thread.setName('主线程')#设置线程名字
print('线程名字:',thread.getName())#获取当前线程名字
new_th=threading.enumerate()#获取正在运行的线程
print('正在运行的线程',new_th)
print('正在运行的线程个数:',threading.active_count())#正在运行的线程个数
执行命令得
[0, 1, 2, 3, 4, 5, 6, 7, 8]
线程名字: 主线程
正在运行的线程 [<_MainThread(主线程, started 12184)>]
正在运行的线程个数: 1
除了使用方法外,线程模块同样提供了Thread类来处理线程,Thread类提供了以下方法
方法 | 描述 |
run() | 用以表示线程活动的方法 |
start() | 启动线程活动 |
join([time]) | 等待至线程终止,这阻塞调用线程直至线程的join()方法 被调用终止,正常退出或者抛出未处理的异常或者是可选的超时发生 |
isAlive() | 返回线程是否活动的 |
getName() | 返回线程名 |
setName() | 设置线程名 |
线程的状态
Python中使用线程有两种方式:函数或者类来包装线成对像.
3.函数式:调用thread模块中的start_new_thread()函数来产生新线路.语法如下
thread.start_new_thread(function,args[,kwargs])
参数说明:
function--线程函数
args--传递给线程函数的参数,他必须是个tuple类型
kwargs--可选参数
注意:函数实现方式:线程必须依赖函数实现,不能单独运行.当函数结束,线程结束.所以如果想知道线程一直运行,就要想办法让程序不结束,比如在程序最后加一个input(),或死循环
import threading,time
def something(x):
for i in range(1,x):
print(i)
time.sleep(0.2)
threading._start_new_thread(something,(10,))#启动一个新的线程 括号里添加参数并且参数必须是元组
input()
执行命令得
1
2
3
4
5
6
7
8
9
例:
时间线程
import time,_thread
# 为线程定义一个函数
def print_time(threadName, delay):
count = 0
while count < 5:
time.sleep(delay)
count += 1
print( "%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")
while 1:
pass
执行命令得
Thread-1: Thu May 31 11:48:44 2018
Thread-2: Thu May 31 11:48:46 2018
Thread-1: Thu May 31 11:48:46 2018
Thread-1: Thu May 31 11:48:48 2018
Thread-2: Thu May 31 11:48:50 2018
Thread-1: Thu May 31 11:48:50 2018
Thread-1: Thu May 31 11:48:52 2018
Thread-2: Thu May 31 11:48:54 2018
Thread-2: Thu May 31 11:48:58 2018
Thread-2: Thu May 31 11:49:02 2018
4.线程类
<1>继承threading.Thread
<2>写构造方法,且必须调用父类的构造方法
<3>重写父类run方法,会在start之后自动调用
<4>实现开始方法,如果重写了start()方法,一定要调用父类的start()
程序交替执行
import threading,time
class Mythread(threading.Thread):#继承父类threading.Thread
def __init__(self):
threading.Thread.__init__(self)
print('Mythread __init__()')
def run(self): #把要执行的代码写到run函数里面 线程在创建后会直接运行run函数
for i in range(3):
print(self.getName(),i)
time.sleep(1)#等待时间
t1=Mythread()
t2=Mythread()
t1.start()
t2.start()
print('正在运行的线程个数:',threading.active_count())
执行命令得
Mythread __init__()
Mythread __init__()
Thread-1 0
Thread-2 0
正在运行的线程个数: 3
Thread-1 1
Thread-2 1
Thread-1 2
Thread-2 2
程序先后执行(并没有以线程格式去执行而是调用了run方法)
import threading,time
class Mythread(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
print('Mythread __init__()')
def run(self):
for i in range(3):
print(self.getName(),i)
time.sleep(1)#等待时间
t1=Mythread()
t2=Mythread()
t1.run()
t2.run()
print('正在运行的线程个数:',threading.active_count())
执行命令得
Mythread __init__()
Mythread __init__()
Thread-1 0
Thread-1 1
Thread-1 2
Thread-2 0
Thread-2 1
Thread-2 2
正在运行的线程个数: 1
join()#加入并阻断主线程的执行.即执行完才执行主线程,可以加时间,join(3)阻断3秒结束阻断
import threading,time
class Mythread(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
print('Mythread __init__()')
def run(self):
for i in range(6):
print(self.getName(),i)
time.sleep(1)#等待时间
t1=Mythread()
t1.start()
for i in range(6):
print(threading.current_thread().getName(), i)
time.sleep(1) # 等待时间
if i ==2:
# 哪个线程调用停止哪个
t1.join()
执行命令得
Mythread __init__()
MainThread 0
Thread-1 0
MainThread 1
Thread-1 1
MainThread 2
Thread-1 2
Thread-1 3
Thread-1 4
Thread-1 5
MainThread 3
MainThread 4
MainThread 5
练习
数据的共享
抢票系统
第一种方法:(此方法只有一条主线程在执行)
import threading,time
num=10
count=0
def qiangpiao(x):
global num,count
while True:
if num==0:
return#结束当前方法
num=num-1
count=count+1
print('{0}抢到了 第{1}张 剩余{2}'.format(x,count,num))
time.sleep(0.2)
threading._start_new_thread(qiangpiao,('张三',))
threading._start_new_thread(qiangpiao,('李四',))
threading._start_new_thread(qiangpiao,('王五',))
input()
执行命令得
王五抢到了 第1张 剩余9
张三抢到了 第2张 剩余8
李四抢到了 第3张 剩余7
李四抢到了 第4张 剩余6
王五抢到了 第6张 剩余4
张三抢到了 第5张 剩余5
李四抢到了 第7张 剩余3
张三抢到了 第8张 剩余2
王五抢到了 第9张 剩余1
张三抢到了 第10张 剩余0
第二种方法:(多线程同时交替执行)
import threading,time
num=20
count=0
class qiangpiao(threading.Thread):
def __init__(self,name):
threading.Thread.__init__(self)
self.setName(name)
def run(self):
global num,count
while True:
if num==0:
return
num=num-1
count=count+1
print('{0}抢到了第{1}张 剩余{2}张'.format(self.getName(),count,num))
time.sleep(0.2)
if __name__=='__main__':
huangniu=qiangpiao('黄牛')
phone=qiangpiao('手机')
chuangkou=qiangpiao('窗口')
huangniu.start()
phone.start()
chuangkou.start()
print('正在运行的线程个数:', threading.active_count())
执行命令得
黄牛抢到了第1张 剩余19张
手机抢到了第2张 剩余18张
窗口抢到了第3张 剩余17张
正在运行的线程个数: 4
手机抢到了第4张 剩余16张
黄牛抢到了第5张 剩余15张
窗口抢到了第6张 剩余14张
手机抢到了第7张 剩余13张
黄牛抢到了第8张 剩余12张
窗口抢到了第9张 剩余11张
手机抢到了第10张 剩余10张
窗口抢到了第11张 剩余9张
黄牛抢到了第12张 剩余8张
手机抢到了第13张 剩余7张
黄牛抢到了第14张 剩余6张
窗口抢到了第15张 剩余5张
手机抢到了第16张 剩余4张
黄牛抢到了第17张 剩余3张
窗口抢到了第18张 剩余2张
手机抢到了第19张 剩余1张
黄牛抢到了第20张 剩余0张
5.线程同步
如果多个线程共同对某个数据修改,则可能出现不可预料的结果,为了保证数据的正确性,需要对多个线程进行同步所以有了锁的概念,我们通过锁来使多个线程任务更加安全(效率低)
lock=threading.Lock()
cond=threading.Condition(lock=lock)
由于并发的问题,需要加锁:
锁当然有锁定和未锁定两种状态,当一个线程需要访问共享数据时,必须要先获得锁定,如果已经有别的线程获得锁定,那么久进入暂停状态,等别的线程把锁释放后,再进行操作
Condition:更精确的控制锁,提供了四个方法,
上锁(acquire())
等待(wait())
解锁(release())
唤醒(notify(),notify_all())
(加锁后让资源更加安全不会出现)
例:
遍历出1-10 和 30-20 当第一个线程得到3时加锁等待第二个线程完成后继续遍历
import threading,time
class Thread1(threading.Thread):
def run(self):
for i in range(1,11):
if i==3:
cond.acquire()#某个线程获得资源就加上锁
cond.wait() #等待
cond.release()#某个线程完成了处理就释放锁
print(i)
time.sleep(1)
class Thread2(threading.Thread):
def run(self):
for i in range(30,19,-1):
print(i)
time.sleep(1)
cond.acquire()
cond.notify()
cond.release()
lock = threading.Lock()#创建一把锁
cond = threading.Condition(lock=lock)#管理一把锁
t1 = Thread1()
t2 = Thread2()
t1.start()
t2.start()
1
30
29
2
28
27
26
25
24
23
22
21
20
3
4
5
6
7
8
9
10
练习
蒸包子吃包子循环系统
import threading,time
zhenglong=[]#共享数据--蒸笼
#创建两把锁
# 一把蒸包子三的锁 由伙夫掌管
#另外一把吃包子的锁 由吃货掌管
zheng_lock=threading.Lock()
chi_lock=threading.Lock()
zheng_Cond=threading.Condition(lock=zheng_lock)
chi_Cond=threading.Condition(lock=chi_lock)
class huofu(threading.Thread):
def __init__(self,name):
threading.Thread.__init__(self)
self.setName(name)
def run(self):
while True:
chi_Cond.acquire()# 被谁唤醒
if len(zhenglong)==0:
#开始蒸包子
for i in range(1,11):
zhenglong.append(i)
time.sleep(0.1)
print('正在蒸第{0}个包子'.format(i))
print('包子蒸完了 唤醒吃货')
chi_Cond.notify_all()#唤醒吃货们
chi_Cond.release()#唤醒了伙夫 他就解锁
#伙夫进入休眠
zheng_Cond.acquire()
zheng_Cond.wait()
zheng_Cond.release()
class chihuo(threading.Thread):
def __init__(self,name):
threading.Thread.__init__(self)
self.setName(name)
def run(self):
while True:
chi_Cond.acquire()#同一时刻只有一个吃货在获取吃包子的资源
global zhenglong
if len(zhenglong)==0:
#开始呼唤伙夫 只交叫一次 蒸包子 我和其他吃货一同进入休眠
zheng_Cond.acquire()#锁定叫醒伙夫的线程
zheng_Cond.notify()#唤醒
zheng_Cond.release()#释放
chi_Cond.wait()#这个吃货进入休眠
else:
baozi=zhenglong.pop()
print('{0}吃了第{1}个包子 剩余{2}个包子'.format(self.getName(),baozi,len(zhenglong)))
time.sleep(0.1)
chi_Cond.release()
w=huofu('伙夫')
xiaoming=chihuo('小明')
xiaopang=chihuo('小胖')
w.start()
xiaoming.start()
xiaopang.start()
input()
执行命令得
正在蒸第1个包子
正在蒸第2个包子
正在蒸第3个包子
正在蒸第4个包子
正在蒸第5个包子
正在蒸第6个包子
正在蒸第7个包子
正在蒸第8个包子
正在蒸第9个包子
正在蒸第10个包子
包子蒸完了 唤醒吃货
小明吃了第10个包子 剩余9个包子
小胖吃了第9个包子 剩余8个包子
小胖吃了第8个包子 剩余7个包子
小明吃了第7个包子 剩余6个包子
小明吃了第6个包子 剩余5个包子
小胖吃了第5个包子 剩余4个包子
小胖吃了第4个包子 剩余3个包子
小胖吃了第3个包子 剩余2个包子
小明吃了第2个包子 剩余1个包子
小明吃了第1个包子 剩余0个包子
正在蒸第1个包子
正在蒸第2个包子
.....