Python 多线程 多进程 协程 yield
2017-08-20 20:32
896 查看
python中多线程和多进程的最大区别是稳定性和效率问题
多进程互相之间不影响,一个崩溃了不影响其他进程,稳定性高
多线程因为都在同一进程里,一个线程崩溃了整个进程都完蛋
多进程对系统资源开销大,多线程对系统资源开销小,所以这方面来说多线程会比多进程快一点点
关于线程和进程的详细使用方法这里有https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/0014319272686365ec7ceaeca33428c914edf8f70cca383000
等看完协程再补上
i/o密集型任务瓶颈都在网络,磁盘这些地方,适合用脚本语言进行多任务操作
协程看上去也是子程序,但执行过程中,在子程序内部可中断,然后转而执行别的子程序,在适当的时候再返回来接着执行。
协
程最大的优势是高执行效率,因为子程序切换不是线程切换,而是由程序自己控制,没有切换线程的开销
不需要多线程锁
协程是建立在生成器基础上的,所以需要先理解迭代器生成器!!!
在一个线程里面不等待IO操作返回的结果,通过消息轮询来发送一个IO操作的请求后就执行其他的,等IO操作返回结果消息了再处理.这个不死等的方式不需要多线程多进程,在一个线程里实现,大大的提高了运行效率
对序列,字典,文件都可以使用iter()方法生成可迭代对象,然后用next()方法访问,这种东西咱们叫迭代器,一般用for循环读出内容
生成器是可迭代的
dir(my_generator ) 里面有iter()和next()属性,说明生成器是迭代器,可以用for循环读取内部的值
当第一遍循环的时候,将 my_generator 里面的值依次读出并打印,但是,当再读一次的时候,就发现没有任何结果。这种特性也正是迭代器所具有的,因为已经迭代到最后,指针指向没有内容了
生成器my_generator = (x*x for x in range(4))和列表解析式my_list = [x*x for x in range(4)]有啥不一样的地方呢,列表是先划分出内存来放列表中的数据的,生成器是用到的时候再申请内存,针对大量值的时候,列表占内存较多,迭代器(生成器是迭代器)的优势就在于少占内存,还有一点区别就是上面那个for循环读取内部的值,列表是可以反复取值的,不像生成器指针到最后没有了就不走了,列表的内存划分好了,每次想取值都可以
比如
有iter和next,说明是迭代器,用lalalal.next()可以取值的
从上面的例子可以明白,含有yield关键字的函数返回值是一个生成器类型的对象,也是迭代器
我们任性的吧含有yield语句的函数叫做生成器,生成器是一种用普通函数语法定义的迭代器,反正记住,普通函数只要用了yield就变态成为生成器了,当然生成器具备迭代器属性
我们来看看在函数里 yield和return的具体区别
一般的函数,都是止于 return。作为生成器的函数,由于有了 yield,则会遇到它挂起,如果还有 return,遇到它就直接抛出 SoptIteration 异常而中止迭代。
使用send可以接受一个外部传入的变量,然后根据变量内容计算结果之后返回,咱们之后要说的协程就是靠生成器函数的这个特性
<
c525
pre class="prettyprint">
说下流程
这里和传统函数调用不一样,敲黑板,要通过r.send(None)(ps:如果用了send起手必须传None)或者r.next()或者next(r)来启动生成器函数,并进行到第一个yield语句结束的位置.此时,执行完了yield这一行语句,这个时候括号里的yield n返回初始值0,返回值n=0
然后send(“new friend come in”)这里会传入new friend come in,从下一行开始继续执行,并回到while头部,执行yield n这一行返回n=new friend come in了之后又停下来了,
.再执行r.send(“tseeee”),重复上一步,执行到yield n这一行返回n=tseeee之后再一次停下来
多进程互相之间不影响,一个崩溃了不影响其他进程,稳定性高
多线程因为都在同一进程里,一个线程崩溃了整个进程都完蛋
多进程对系统资源开销大,多线程对系统资源开销小,所以这方面来说多线程会比多进程快一点点
关于线程和进程的详细使用方法这里有https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/0014319272686365ec7ceaeca33428c914edf8f70cca383000
等看完协程再补上
i/o密集型任务瓶颈都在网络,磁盘这些地方,适合用脚本语言进行多任务操作
3.协程
子程序调用总是一个入口,一次返回,调用顺序是明确的。而协程的调用和子程序不同。协程看上去也是子程序,但执行过程中,在子程序内部可中断,然后转而执行别的子程序,在适当的时候再返回来接着执行。
协
程最大的优势是高执行效率,因为子程序切换不是线程切换,而是由程序自己控制,没有切换线程的开销
不需要多线程锁
协程是建立在生成器基础上的,所以需要先理解迭代器生成器!!!
在一个线程里面不等待IO操作返回的结果,通过消息轮询来发送一个IO操作的请求后就执行其他的,等IO操作返回结果消息了再处理.这个不死等的方式不需要多线程多进程,在一个线程里实现,大大的提高了运行效率
对序列,字典,文件都可以使用iter()方法生成可迭代对象,然后用next()方法访问,这种东西咱们叫迭代器,一般用for循环读出内容
生成器是可迭代的
简单的生成器
my_generator = (x*x for x in range(4))
dir(my_generator ) 里面有iter()和next()属性,说明生成器是迭代器,可以用for循环读取内部的值
>>> for i in my_generator: ... print i ... 0 1 4 9 >>> for i in my_generator: ... print i ...
当第一遍循环的时候,将 my_generator 里面的值依次读出并打印,但是,当再读一次的时候,就发现没有任何结果。这种特性也正是迭代器所具有的,因为已经迭代到最后,指针指向没有内容了
生成器my_generator = (x*x for x in range(4))和列表解析式my_list = [x*x for x in range(4)]有啥不一样的地方呢,列表是先划分出内存来放列表中的数据的,生成器是用到的时候再申请内存,针对大量值的时候,列表占内存较多,迭代器(生成器是迭代器)的优势就在于少占内存,还有一点区别就是上面那个for循环读取内部的值,列表是可以反复取值的,不像生成器指针到最后没有了就不走了,列表的内存划分好了,每次想取值都可以
>>> for i in my_list: ... print i ... 0 1 4 9 >>> for i in my_list: ... print i ... 0 1 4 9
yield
python中有个词yield ,这家伙尼玛是生成器的标志比如
def g(): yield 0 yield 1 yield 2 lalalal = g() print type(lalalal) print dir(lalalal)
#输出 <type 'generator'> ['__class__', '__delattr__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__iter__', '__name__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'close', 'gi_code', 'gi_frame', 'gi_running', 'next', 'send', 'throw']
有iter和next,说明是迭代器,用lalalal.next()可以取值的
从上面的例子可以明白,含有yield关键字的函数返回值是一个生成器类型的对象,也是迭代器
我们任性的吧含有yield语句的函数叫做生成器,生成器是一种用普通函数语法定义的迭代器,反正记住,普通函数只要用了yield就变态成为生成器了,当然生成器具备迭代器属性
我们来看看在函数里 yield和return的具体区别
def r_return(n): print "You taked me." while n > 0: print "before return" return n n -= 1 print "after return" rr = r_return(3) print rr #输出 You taked me. before return 3 #可以看出来,普通函数遇到return将值返回玩后,函数就不往下继续执行了 #再看用yield将函数变为generator生成器之后的样子 def r_return(n): print "You taked me." while n > 0: print "before return" yield n n -= 1 print "after return" rr = r_return(3) print rr.next() print rr.next() print rr.next() #输出 You taked me. before return 3 after return before return 2 after return before return 1 #可以看出,用了yield比return好啊,返回完值(迭代一次),还可以再接着执行后面的内容(迭代第二次,第三次),直到跳出循环(没有可迭代的东西了)
一般的函数,都是止于 return。作为生成器的函数,由于有了 yield,则会遇到它挂起,如果还有 return,遇到它就直接抛出 SoptIteration 异常而中止迭代。
send
上面的生成器都是固定的,肚子里有啥就输出什么,自从python2.5之后,生成器有了一个新的特性,就是send方法,用它能直接往生成器的肚子里面传递数据了,让生成器不再是固定输出了使用send可以接受一个外部传入的变量,然后根据变量内容计算结果之后返回,咱们之后要说的协程就是靠生成器函数的这个特性
<
c525
pre class="prettyprint">
def repeater(): n=None while 1: n = (yield n) r= repeater() r.send(None) print r.send("new friend come in") print r.send("tseeee") #输出 new friend come in tseeee
说下流程
这里和传统函数调用不一样,敲黑板,要通过r.send(None)(ps:如果用了send起手必须传None)或者r.next()或者next(r)来启动生成器函数,并进行到第一个yield语句结束的位置.此时,执行完了yield这一行语句,这个时候括号里的yield n返回初始值0,返回值n=0
然后send(“new friend come in”)这里会传入new friend come in,从下一行开始继续执行,并回到while头部,执行yield n这一行返回n=new friend come in了之后又停下来了,
.再执行r.send(“tseeee”),重复上一步,执行到yield n这一行返回n=tseeee之后再一次停下来
相关文章推荐
- python并发编程之多进程、多线程、异步和协程详解
- Python多进程、多线程、协程学习小结
- python3-----多进程、多线程、多协程
- 深入浅析python中的多进程、多线程、协程
- python学习之路-11 多线程、多进程、协程
- python并发编程之多进程、多线程、异步和协程
- python并发编程之多进程、多线程、异步和协程
- python2 多线程和多进程、协程入门讲解
- python 多线程、多进程、协程性能对比(以爬虫为例)
- 也说性能测试,顺便说python的多进程+多线程、协程
- Python之多进程、多线程、协程和分布式进程
- 深入浅析python中的多进程、多线程、协程
- python多进程、多线程、协程向mysql插入10000条数据
- python并发编程之多进程、多线程、异步和协程详解
- Python 多进程 多线程 协程 I/O多路复用
- python并发编程之多进程、多线程、异步和协程详解
- Python 多线程多进程10.4.1 应用于自动化测试项目
- Python多线程多进程和线性执行的比较
- [python] 连接MySQL,以及多线程、多进程连接MySQL初探
- Python多线程与多进程