python学习笔记:3 io操作

文件读写

可以使用open来操作文件,但是每次都要close

1
2
3
4
5
6
try:
f = open('iotest.txt', 'rb')
print f.read()
finally:
if f:
f.close()

所以推荐使用with ,能自动完成close

1
2
with open('iotest.txt', 'rb') as f:
print f.read().decode('gbk')

练习:遍历目录下所有文件,查找文件名包含test的文件

1
2
3
4
5
6
7
8
9
10
11
12
13
absolute_path = sys.path[0]
#print absolute_path
def search(path,name):
for x in os.listdir(path):
fullname = os.path.join(path,x)
if os.path.isfile(fullname):
#print '文件:%s' % fullname
if name in x:
print '选中:%s' % fullname
else:
search(fullname,name)

search(absolute_path,'test')

序列化

我们把变量从内存中变成可存储或传输的过程称之为序列化,在Python中叫pickling,在其他语言中也被称之为serialization,marshalling,flattening等等,都是一个意思

序列化文件:

1
2
3
f = open('dump.txt', 'wb')
pickle.dump(dic, f)
f.close()

反序列化文件

1
2
3
f = open('dump.txt', 'rb')
d = pickle.load(f)
f.close()

字典序列化为json

1
2
3
str_json = json.dumps(dic)
print str_json
print json.loads(str_json)

对象序列化为json

1
2
3
4
5
6
7
8
9
10
class Student(object):
def __init__(self,name,age,score):
self.name = name
self.age = age
self.score = score
def student2dict(self,object):
return {'name':self.name,'age':self.age,'score':self.score}

hammer = Student('hammer',27,100)
print json.dumps(hammer,default=hammer.student2dict)

多进程

unix/lunix使用fork(),会复制当前进程出一个子进程

子进程永远返回0,而父进程返回子进程的ID。这样做的理由是,一个父进程可以fork出很多子进程,所以,父进程要记下每个子进程的ID,而子进程只需要调用getppid()就可以拿到父进程的ID。

Python的os模块封装了常见的系统调用,其中就包括fork,可以在Python程序中轻松创建子进程:
Progress
使用Progress来写快平台多进程

1
2
3
4
5
6
7
8
9
10
11
12
# 1 使用Process来创建进程
def run_proc(name):
print 'Run child process %s (%s)...' % (name, os.getpid())

if __name__=='__main__':
print 'Parent process %s.' % os.getpid()
p = Process(target=run_proc, args=('test',))
print 'Process will start.'
p.start()
p.join()
print 'Process end.'
####################

Pool
使用Pool进程池,来批量创造进程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#2 学习使用Pool,进程池
def long_time_task(name):
print '执行 tast %s(%s)...' % (name,os.getpid())
start = time.time()
time.sleep(random.random() * 3 )
end = time.time()
print 'Task %s run %0.2f seconds.' % (name,end - start)

if __name__ =='__main__':
print '父进程id %s .' % os.getpid()
p = Pool()
for i in range(5):
p.apply_async(long_time_task,args=(i,))
print '等待所有子进程执行完毕.'
p.close() #close之后Pool不能新增子进程了
p.join() # join方法会等待所有子进程执行完毕
print 'All done .'
#########################

进程间通信

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# 3 学习使用Queue,实现进程间通信
# 写数据进程执行的代码:
def write(q):
for value in ['A', 'B', 'C']:
print 'Put %s to queue...' % value
q.put(value)
time.sleep(random.random())

# 读数据进程执行的代码:
def read(q):
while True:
value = q.get(True)
print 'Get %s from queue.' % value

if __name__=='__main__':
# 父进程创建Queue,并传给各个子进程:
q = Queue()
pw = Process(target=write, args=(q,))
pr = Process(target=read, args=(q,))
# 启动子进程pw,写入:
pw.start()
# 启动子进程pr,读取:
pr.start()
# 等待pw结束:
pw.join()
# pr进程里是死循环,无法等待其结束,只能强行终止:
pr.terminate()

多线程

Python是真正的多线程。
Python的标准库提供了两个模块:threadthreadingthread是低级模块,threading是高级模块,对thread进行了封装。绝大多数情况下,我们只需要使用threading这个高级模块。

Python解释器由于设计时有GIL全局锁,导致了多线程无法利用多核。多线程的并发在Python中就是一个美丽的梦。
意思是Python虽然是实际设计的多线程,但是由于全局所的存在,无法使用CPU的多核性能

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 学习使用多线程,主要是threading
import time,threading
def loop():
print 'thread %s is running ...' % threading.current_thread().name
n = 0
while n < 5:
n = n+1
print 'thread %s >>> %s' % (threading.current_thread().name,n)
time.sleep(1)
print 'thread %s ended.' % threading.current_thread().name
print 'thread %s is running...' % threading.current_thread().name
t = threading.Thread(target=loop,name = 'ChildThread')
t.start()
t.join()
print 'thread %s ended.' % threading.current_thread().name

选择进程还是线程

如果用多进程实现Master-Worker,主进程就是Master,其他进程就是Worker。

如果用多线程实现Master-Worker,主线程就是Master,其他线程就是Worker。

  • cpu密集型:典型的是计算圆周率,视频解码
  • io密集型:典型的是web服务器

    如果充分利用操作系统提供的异步IO支持,就可以用单进程单线程模型来执行多任务,这种全新的模型称为事件驱动模型,Nginx就是支持异步IO的Web服务器。它在单核CPU上采用单进程模型就可以高效地支持多任务。在多核CPU上,可以运行多个进程(数量与CPU核心数相同)。
    python单进程的异步编程模型称为协程,有了协程的支持,就可以基于事件驱动编写高效的多任务程序.
    类似于nodejs服务器,也是采用的基于事件驱动的单进程单线程来执行多任务。

分布式进程

为什么选用Process,而不是Thread呢,因为进程可以部署到不同的机器上,形成分布式进程。
比如:
机器1》 创建Queue,把Queue注册到网络上暴露,供其他进程访问