您的位置:首页 > 编程语言 > Python开发

day10 python学习随笔

2015-12-28 17:10 330 查看
多路复用
Linux中的 select,poll,epoll 都是IO多路复用的机制。

Python

Python中有一个select模块,其中提供了:select、poll、epoll三个方法,分别调用系统的 select,poll,epoll 从而实现IO多路复用。

注意:网络操作、文件操作、终端操作等均属于IO操作,对于windows只支持Socket操作,其他系统支持其他IO操作,但是无法检测 普通文件操作 自动上次读取是否已经变化
#linux: pipes open() socket windows: socket

select方法

select pipes
#ansible源码

import os
import sys
import shlex
import subprocess
import select

def run_cmd(cmd, live=False, readsize=10):

#readsize = 10

cmdargs = shlex.split(cmd)
p = subprocess.Popen(cmdargs, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

stdout = ''
stderr = ''
rpipes = [p.stdout, p.stderr]
while True:
rfd, wfd, efd = select.select(rpipes, [], rpipes, 1)

if p.stdout in rfd:
dat = os.read(p.stdout.fileno(), readsize)
if live:
sys.stdout.write(dat)
stdout += dat
if dat == '':
rpipes.remove(p.stdout)
if p.stderr in rfd:
dat = os.read(p.stderr.fileno(), readsize)
stderr += dat
if live:
sys.stdout.write(dat)
if dat == '':
rpipes.remove(p.stderr)
# only break out if we've emptied the pipes, or there is nothing to
# read from and the process has finished.
if (not rpipes or not rfd) and p.poll() is not None:
break
# Calling wait while there are still pipes to read can cause a lock
elif not rpipes and p.poll() == None:
p.wait()

return p.returncode, stdout, stderr


#!/usr/bin/env python
# -*- coding:utf-8 -*-
import select
import threading
import sys
while True:
readable, writeable, error = select.select([sys.stdin,],[],[],1)
if sys.stdin in readable:
print 'select get stdin',sys.stdin.readline()
利用select监听终端操作实例
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import socket
import select
sk1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sk1.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sk1.bind(('127.0.0.1',8002))
sk1.listen(5)
sk1.setblocking(0)
inputs = [sk1,]
while True:
readable_list, writeable_list, error_list = select.select(inputs, [], inputs, 1)
for r in readable_list:
# 当客户端第一次连接服务端时
if sk1 == r:
print 'accept'
request, address = r.accept()
request.setblocking(0)
inputs.append(request)
# 当客户端连接上服务端之后,再次发送数据时
else:
received = r.recv(1024)
# 当正常接收客户端发送的数据时
if received:
print 'received data:', received
# 当客户端关闭程序时
else:
inputs.remove(r)
sk1.close()
利用select实现伪同时处理多个Socket客户端请求:服务端
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import socket
import select
sk1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sk1.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sk1.bind(('127.0.0.1',8002))
sk1.listen(5)
sk1.setblocking(0)
inputs = [sk1,]
while True:
readable_list, writeable_list, error_list = select.select(inputs, [], inputs, 1)
for r in readable_list:
# 当客户端第一次连接服务端时
if sk1 == r:
print 'accept'
request, address = r.accept()
request.setblocking(0)
inputs.append(request)
# 当客户端连接上服务端之后,再次发送数据时
else:
received = r.recv(1024)
# 当正常接收客户端发送的数据时
if received:
print 'received data:', received
# 当客户端关闭程序时
else:
inputs.remove(r)
sk1.close()
利用select实现伪同时处理多个Socket客户端请求:服务端
此处的Socket服务端相比与原生的Socket,他支持当某一个请求不再发送数据时,服务器端不会等待而是可以去处理其他请求的数据。但是,如果每个请求的耗时比较长时,select版本的服务器端也无法完成同时操作。


事件

python线程的事件用于主线程控制其他线程的执行,事件主要提供了三个方法 set、wait、clear。
事件处理的机制:全局定义了一个“Flag”,如果“Flag”值为 False,那么当程序执行 event.wait 方法时就会阻塞,如果“Flag”值为True,那么event.wait 方法时便不再阻塞。
clear:将“Flag”设置为False

set:将“Flag”设置为True

#!/usr/bin/env python
# -*- coding:utf-8 -*-

import threading

def do(event):
print 'start'
event.wait()
print 'execute'

event_obj = threading.Event()
for i in range(10):
t = threading.Thread(target=do, args=(event_obj,))
t.start()

event_obj.clear()
inp = raw_input('input:')
if inp == 'true':
event_obj.set()


Python 进程
from multiprocessing import Process
import threading
import time

def foo(i):
print 'say hi',i

for i in range(10):
p = Process(target=foo,args=(i,))
p.start()
注意:由于进程之间的数据需要各自持有一份,所以创建进程需要的非常大的开销。
进程数据共享
进程各自持有一份数据,默认无法共享数据
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  进程 python