1 multiprocessing模块

(1.)直接导入
from multiprocessing import Process
import os
import time
def info(name):
print("name:",name)
print('parent process:', os.getppid())
print('process id:', os.getpid())
print("------------------")
def foo(name):
info(name)
time.sleep(50)
if __name__ == '__main__':
info('main process line')
p1 = Process(target=info, args=('alvin',))
p2 = Process(target=foo, args=('egon',))
p1.start()
p2.start() p1.join()
p2.join() print("ending")
time.sleep(100)
>>
name: main process line
parent process: 16976
process id: 18456
------------------
name: alvin
parent process: 18456
process id: 19884
------------------
name: egon
parent process: 18456
process id: 19112
------------------
ending

  

(2.)创建类的方法

构造方法:

Process([group [, target [, name [, args [, kwargs]]]]])

  group: 线程组,目前还没有实现,库引用中提示必须是None;

  target: 要执行的方法;

  name: 进程名;

args/kwargs: 要传入方法的参数。

实例方法:

  is_alive():返回进程是否在运行。

  join([timeout]):阻塞当前上下文环境的进程程,直到调用此方法的进程终止或到达指定的timeout(可选参数)。

  start():进程准备就绪,等待CPU调度

  run():strat()调用run方法,如果实例进程时未制定传入target,这star执行t默认run()方法。

  terminate():不管任务是否完成,立即停止工作进程

属性:

  daemon:和线程的setDeamon功能一样

  name:进程名字。

  pid:进程号。

2 协程

协程的优点:

(1)     由于单线程不存在切换

(2)     不再有任何锁的概念

yield是最基本的携程函数
没有办法监听到IO,进行切换
可以保存到数据的状态通过send方法来运行
import time
# 注意到consumer函数是一个generator(生成器):
# 任何包含yield关键字的函数都会自动成为生成器(generator)对象 def consumer():
r = ''
while True:
n = yield r
if not n:
return
print('[CONSUMER] ←← Consuming %s...' % n)
time.sleep(1)
r = '200 OK'
def produce(c):
# 1、首先调用c.next()启动生成器
next(c)
n = 0
while n < 5:
n = n + 1
print('[PRODUCER] →→ Producing %s...' % n)
# 2、然后,一旦生产了东西,通过c.send(n)切换到consumer执行;
cr = c.send(n)
# 4、produce拿到consumer处理的结果,继续生产下一条消息;
print('[PRODUCER] Consumer return: %s' % cr)
# 5、produce决定不生产了,通过c.close()关闭consumer,整个过程结束。
c.close()
if __name__=='__main__':
# 6、整个流程无锁,由一个线程执行,produce和consumer协作完成任务,所以称为“协程”,而非线程的抢占式多任务。
c = consumer()
produce(c)

  

greenlet模块

可以实现手动切换

调用属性swich

gevent可以实现IO的监听

gevent.joinall 开启所有程序

gevent.spawn 切换

3 IO模型

IO指input, output

IO发生时涉及的对象和步骤

会涉及到两个系统对象,一个是调用这个IO的process(or thread),另一个就是系统内核(kernel)。当一个操作发生时,会经历两个阶段:

(1)     等待数据准备

(2)     将数据从内核拷贝到进程中

IO模型类型:

  1. 1.      阻塞  IO

  1. 1.      非阻塞 IO

非阻塞IO:发送多次系统调用

优点:wait for data无阻塞

缺点:系统调用太多

不能及时拿到数据

两个阶段:wait for data非阻塞

copy data 阻塞

非阻塞的recvform系统调用调用之后,进程并没有被阻塞,内核马上返回给进程,如果数据还没准备好,此时会返回一个error。进程在返回之后,可以干点别的事情,然后再发起recvform系统调用。重复上面的过程,循环往复的进行recvform系统调用。这个过程通常被称之为轮询。轮询检查内核数据,直到数据准备好,再拷贝数据到进程,进行数据处理。需要注意,拷贝数据整个过程,进程仍然是属于阻塞的状态。

  1. 1.      IO多路复用(监听多个链接)

特点:(1)全程阻塞

能监听多个文件描述符  实现并发

#服务端

import select

import socket

sock=socket.socket()#产生一个套接字

sock.bind(("127.0.0.1",8080))

sock.listen(5)

sock.setblocking(False)

inputs=[sock,]

while 1:

    r,w,e=select.select(inputs,[],[])#监听有变化的套接字sock

    #wait for data

    for obj in r:

        if obj==sock:

            conn,addr=obj.accept()#从内核copy信息到用户态

            print("conn",conn)

            inputs.append(conn)#监听列表添加客户conn

        else:

            data=obj.recv(1024)#接收信息

            print(data.decode("utf8"))

            send_data=input(">>")#发送信息

            obj.send(send_data.encode("utf8"))

#客户端

import socket

sock=socket.socket()

sock.connect(("127.0.0.1",8080))

while 1:

    data=input("input>>")

    sock.send(data.encode("utf8"))

    recv_data=sock.recv(1024)

    print(recv_data.decode("utf8"))

sock.close()

  

对于文件描述符(套接字对象)

(1)    是一个非零整数,不会变

(2)    收发数据的时候,对于接收端而言,数据先到内核空间,然后copy到用户空间,同时,内核空间数据清除

  1. 1.      异步IO

全程无阻塞

5.驱动信号

小结:

有阻塞blocking

无阻塞non-blocking

调用blocking IO会一直block住对应的进程知道操作完成

non-blocking IO在kernel还准备数据的情况下会立刻返回

有阻塞是同步阻塞:阻塞  非阻塞  IO多路复用

无阻塞是异步阻塞:异步IO

4 selectors模块

IO多路复用实现机制

Win:select

Linux:select,poll,epoll

Select缺点:1.每次调用select都要将所有的fd(文件描述符)拷贝到内核空间,导致效率下降

2.遍历所有的fd,是否有数据访问(最重要的问题)

3.最大连接数(1024)

poll:最大连接数没有限制

epoll:1.第一个函数创建epoll句柄,将所有的fd(文件描述符)拷贝到内核空间

只需要拷贝一次

2.回调函数:某一个函数或者某一个动作成功完成之后会触发的函数

为所有的fd绑定一个回调函数,但有数据访问触发该回调函数

回调函数将fd放到列表中

import selectors
import socket
sock=socket.socket()
sock.bind(("127.0.0.1",8080))
sock.listen(5)
sock.setblocking(False)
sel=selectors.DefaultSelector()#根据具体平台选择最佳IO多路机制
def read(conn,mask):
try:
data=conn.recv(1024)
print(data.decode("utf8"))
data2=input(">>")
conn.send(data2.encode("utf8"))
except Exception:
sel.unregister(conn)
def accept(sock,mask):
sel.register(sock,selectors.EVENT_READ,accept)
conn,addr=sock.accept()
sel.register(conn,selectors.EVENT_READ,read)
sel.register(sock,selectors.EVENT_READ,accept)#注册功能
while 1:
events=sel.select()
for key,mask in events:
print(key.data)#定义的函数
print(key.fileobj)#socket对象
func=key.data
obj=key.fileobj
func(obj,mask) break import socket
sock=socket.socket()
sock.connect(("127.0.0.1",8080))
while 1:
data=input("input>>")
sock.send(data.encode("utf8"))
recv_data=sock.recv(1024)
print(recv_data.decode("utf8")) sock.close()

  

5. 队列

队列用在多线程,多进程中,用来保护数据

队列是个数据类型

优点:线程安全

import queue
q=queue.Queue(3)#默认是先进先出
q.put(111)
q.put("hello")
q.put(222)
print(q.get())
print(q.get())
print(q.get())
>>
111
hello
222 import queue
q=queue.Queue(3)#默认是先进先出
q.put(111)
q.put("hello")
q.put(222)
q.put(223,False)#q=queue.Queue(3)队列定义只能放3个值,
# #超过限额时,返回错误信息
print(q.get())
print(q.get())
print(q.get()) q.get()#没有数据的时候不会报错,只会等待
q.get(False)#数据为空,报错 先进后出
import queue
q=queue.LifoQueue()
q.put(111)
q.put(5)
q.put(43)
print(q.get()) 优先级
import queue
q=queue.PriorityQueue()
q.put([4,"hello"])
q.put([1,"hello5"])
print(q.get())

  

python之进程和线程3的更多相关文章

  1. Python的进程与线程--思维导图

    Python的进程与线程--思维导图

  2. Python创建进程、线程的两种方式

    代码创建进程和线程的两种方式 """ 定心丸:Python创建进程和线程的方式基本都是一致的,包括其中的调用方法等,学会一个 另一个自然也就会了. "" ...

  3. python之进程与线程

    什么是操作系统       可能很多人都会说,我们平时装的windows7 windows10都是操作系统,没错,他们都是操作系统.还有没有其他的? 想想我们使用的手机,Google公司的Androi ...

  4. python的进程与线程(二)

    线程 之前了解了操作系统的发展史,也知道了进程和线程的概念,归纳一下就是:         进程:本质上就是一段程序的运行过程(抽象的概念)         线程:最小的执行单元,是进程的实体     ...

  5. Python 9 进程,线程

    本节内容 python GIL全局解释器锁 线程 进程 Python GIL(Global Interpreter Lock) In CPython, the global interpreter l ...

  6. python之进程和线程2

    1  GIL全局解释器锁定义 定义:在一个线程拥有了解释器的访问权后,其他的所有线程都必须等待他释放解释器的访问权,即这些线程的下一条指令并不会互相影响. 缺点:多处理器退化为单处理器 优点:避免大量 ...

  7. python之进程和线程

    1 操作系统 为什么要有操作系统 ? 操作系统位于底层硬件与应用软件之间的一层 工作方式:向下管理硬件,向上提供接口 操作系统进程切换: 出现IO操作 固定时间 2 进程和线程的概念 进程就是一个程序 ...

  8. 《Python》进程收尾线程初识

    一.数据共享 from multiprocessing import Manager 把所有实现了数据共享的比较便捷的类都重新又封装了一遍,并且在原有的multiprocessing基础上增加了新的机 ...

  9. Python基础进程和线程

    一 背景知识 进程的概念起源于操作系统,是操作系统最核心的概念. 进程是对正在运行程序的一个抽象,操作系统的其他所有内容都是围绕进程的概念展开的.所以想要真正了解进程,必须事先了解操作系统,egon介 ...

  10. Python中进程和线程的总体区别

    Num01–>线程 线程是操作系统中能够进行运算调度的最小单位.它被包含在进程之中,是进程中的实际运作单位. 一个线程指的是进程中一个单一顺序的控制流. 一个进程中可以并发多条线程,每条线程并行 ...

随机推荐

  1. [转] css选择器中:first-child与:first-of-type的区别

    :first-child选择器是css2中定义的选择器,从字面意思上来看也很好理解,就是第一个子元素.比如有段代码: p:first-child  匹配到的是p元素,因为p元素是div的第一个子元素: ...

  2. XML与HTML的主要差异

    1. 参考 XML 简介 2. XML 与 HTML 的主要差异 XML 不是 HTML 的替代. XML 和 HTML 为不同的目的而设计: XML 被设计为传输和存储数据,其焦点是数据的内容. H ...

  3. DirectoryEntry配置IIS7出现ADSI Error:未知错误(0x80005000)

    一.错误情况 环境:win7+iis7.0 DirectoryEntry配置IIS7出现如下错误 或者是 下面一段代码在IIS6.0下运转正常,但IIS7.0下运转会出错: System.Direct ...

  4. net core体系-2继续认识net core

    认识net core,net core到底啥?从哪说起呢?我想作为开发的码农,web项目不陌生吧,那就从对应的.net web 对应的net core Web Application项目开始吧. 下面 ...

  5. 请使用千位分隔符(逗号)表示web网页中的大数字

    方法一:使用正则表达式 语法如下: String(Number).replace(/(\d)(?=(\d{3})+$)/g, "$1,"); 举例: String(12345678 ...

  6. 使用aws中国的s3时,制订bucket poicy时注意注意……

    { "Version": "2012-10-17", "Statement": [ { "Sid": "Pub ...

  7. python面试题之Python是如何进行内存管理的

    python内部使用引用计数,来保持追踪内存中的对象,Python内部记录了对象有多少个引用,即引用计数,当对象被创建时就创建了一个引用计数,当对象不再需要时,这个对象的引用计数为0时,它被垃圾回收. ...

  8. union表关联模糊查询servlet,action方法

    2018-11-14 servletxml层 public String getSql(String keyword) { StringBuffer sqlSb = new StringBuffer( ...

  9. es6的分析总结

    1,var let const对比 1,箭头函数的总结 /** * 1,箭头函数没有this,箭头函数this没有被箭头的函数,所以不能使用call,apply,bind改变this指向 * 2,箭头 ...

  10. linux硬盘挂载-新硬盘挂载和扩容硬盘挂载

    这里对当前我实际操作后的两种硬盘挂载进行整理: 第1种是直接添加一块新硬盘,然后进行挂载. 第2种是对硬盘进行扩容后,对扩容后的空间进行分区再进行挂载. [内容为参考网上资料,再加自已实际操作情况进行 ...