进程、线程和协程的区别

进程拥有自己独立的堆和栈,既不共享堆,亦不共享栈,进程由操作系统调度。

线程拥有自己独立的栈和共享的堆,共享堆,不共享栈,线程亦由操作系统调度(标准线程是的)。

协程和线程一样共享堆,不共享栈,协程由程序员在协程的代码里显示调度

协程和线程的区别是:协程避免了无意义的调度,由此可以提高性能,但也因此,程序员必须自己承担调度的责任,同时,协程也失去了标准线程使用多CPU的能力。

Greenlet模块

  1. #!/usr/bin/env python
  2. # -*- coding:utf-8 -*-
  3. from greenlet import greenlet
  4. def test1():
  5. print 12
  6. gr2.switch()
  7. print 34
  8. gr2.switch()
  9. def test2():
  10. print 56
  11. gr1.switch()
  12. print 78
  13. gr1 = greenlet(test1)
  14. gr2 = greenlet(test2)
  15. gr1.switch()

每一个greenlet其实就是一个函数,以及保存这个函数执行时的上下文.对于函数来说上下文也就是其stack。

greenlet需要你自己来处理线程切换, 就是说,你需要自己指定现在执行哪个greenlet再执行哪个greenlet。

Gevent(第三方库)

  1. import gevent
  2. def foo():
  3. print('Running in foo')
  4. gevent.sleep(0)
  5. print('Explicit context switch to foo again')
  6. def bar():
  7. print('Explicit context to bar')
  8. gevent.sleep(0)
  9. print('Implicit context switch back to bar')
  10. gevent.joinall([
  11. gevent.spawn(foo),
  12. gevent.spawn(bar),
  13. ])

gevent是第三方库,通过greenlet实现协程,其基本思想是:

  当一个greenlet遇到IO操作时,比如访问网络,就自动切换到其他的greenlet,等到IO操作完成,再在适当的时候切换回来继续执行。由于IO操作非常耗时,经常使程序处于等待状态,有了gevent为我们自动切换协程,就保证总有greenlet在运行,而不是等待IO。

gevent.sleep()来互相切换,实际上gevent是可以自动切换的。

遇到IO自动切换任务

  1. from gevent import monkey; monkey.patch_all()
  2. import gevent
  3. from urllib.request import urlopen
  4. def f(url):
  5. print('GET: %s' % url)
  6. resp = urlopen(url)
  7. data = resp.read()
  8. print('%d bytes received from %s.' % (len(data), url))
  9. gevent.joinall([
  10. gevent.spawn(f, 'https://www.python.org/'),
  11. gevent.spawn(f, 'https://www.yahoo.com/'),
  12. gevent.spawn(f, 'https://github.com/'),
  13. ])

通过gevent实现单线程下的多socket并发

服务端

  1. import sys
  2. import socket
  3. import time
  4. import gevent
  5. from gevent import socket,monkey
  6. monkey.patch_all()
  7. def server(port):
  8. s = socket.socket()
  9. s.bind(('0.0.0.0', port))
  10. s.listen(500)
  11. while True:
  12. cli, addr = s.accept()
  13. gevent.spawn(handle_request, cli)
  14. def handle_request(conn):
  15. try:
  16. while True:
  17. data = conn.recv(1024)
  18. print("recv:", data)
  19. conn.send(data)
  20. if not data:
  21. conn.shutdown(socket.SHUT_WR)
  22. except Exception as ex:
  23. print(ex)
  24. finally:
  25. conn.close()
  26. if __name__ == '__main__':
  27. server(8001)

客户端

  1. import socket
  2. HOST = 'localhost' # The remote host
  3. PORT = 8001 # The same port as used by the server
  4. s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  5. s.connect((HOST, PORT))
  6. while True:
  7. msg = bytes(input(">>:"),encoding="utf8")
  8. s.sendall(msg)
  9. data = s.recv(1024)
  10. #print(data)
  11. print('Received', repr(data))
  12. s.close()

事件驱动模型

目前大部分的UI编程都是事件驱动模型,如很多UI平台都会提供onClick()事件,这个事件就代表鼠标按下事件。事件驱动模型大体思路如下:

  1. 有一个事件(消息)队列;
  2. 鼠标按下时,往这个队列中增加一个点击事件(消息);
  3. 有个循环,不断从队列取出事件,根据不同的事件,调用不同的函数,如onClick()、onKeyDown()等;
  4. 事件(消息)一般都各自保存各自的处理函数指针,这样,每个消息都有独立的处理函数;

Python自动化之select、greenlet和gevent和事件驱动模型初探的更多相关文章

  1. Python的requests、greenlet和gevent模块在windows下安装

    一.requests模块在windows下安装 Linux系统下requests的安装方法在http://docs.python-requests.org/en/latest/user/install ...

  2. Python自动化开发 - select模块

    介绍: IO-多路复用:监听多个socker对象是否有变化,包括可读.可写.发送错误 Python中的select模块专注于I/O多路复用,提供了select poll epoll三个方法(其中后两个 ...

  3. Python自动化之select解析

    select原理 网络通信被Unix系统抽象为文件的读写,通常是一个设备,由设备驱动程序提供,驱动可以知道自身的数据是否可用.支持阻塞操作的设备驱动通常会实现一组自身的等待队列,如读/写等待队列用于支 ...

  4. Python之路-python(Queue队列、进程、Gevent协程、Select\Poll\Epoll异步IO与事件驱动)

    一.进程: 1.语法 2.进程间通讯 3.进程池 二.Gevent协程 三.Select\Poll\Epoll异步IO与事件驱动 一.进程: 1.语法 简单的启动线程语法 def run(name): ...

  5. Python自动化 【第十篇】:Python进阶-多进程/协程/事件驱动与Select\Poll\Epoll异步IO

    本节内容: 多进程 协程 事件驱动与Select\Poll\Epoll异步IO   1.  多进程 启动多个进程 进程中启进程 父进程与子进程 进程间通信 不同进程间内存是不共享的,要想实现两个进程间 ...

  6. {python之协程}一 引子 二 协程介绍 三 Greenlet 四 Gevent介绍 五 Gevent之同步与异步 六 Gevent之应用举例一 七 Gevent之应用举例二

    python之协程 阅读目录 一 引子 二 协程介绍 三 Greenlet 四 Gevent介绍 五 Gevent之同步与异步 六 Gevent之应用举例一 七 Gevent之应用举例二 一 引子 本 ...

  7. python中的协程:greenlet和gevent

    python中的协程:greenlet和gevent 协程是一中多任务实现方式,它不需要多个进程或线程就可以实现多任务. 1.通过yield实现协程: 代码: import time def A(): ...

  8. Python自动化运维之15、网络编程之socket、socketserver、select、twisted

    一.TCP/IP相关知识 TCP/UDP提供进程地址,两个协议互不干扰的独自的协议       TCP :Transmission Control Protocol 传输控制协议,面向连接的协议,通信 ...

  9. 【python自动化第十一篇】

    [python自动化第十一篇:] 课程简介 gevent协程 select/poll/epoll/异步IO/事件驱动 RabbitMQ队列 上节课回顾 进程: 进程的诞生时为了处理多任务,资源的隔离, ...

随机推荐

  1. Java——Swing

  2. HTML学习笔记——图片显示、图片跳转、图片相对路径

    1>显示图片.用a标签实现点击图片跳转.地图标签/点击图片上固定区域跳转 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transit ...

  3. MONO加载DLL调试命令

    http://www.mono-project.com/docs/advanced/pinvoke/dllnotfoundexception/ http://www.mono-project.com/ ...

  4. Spring中加载xml配置文件的六种方式

    Spring中加载xml配置文件的六种方式 博客分类: Spring&EJB XMLSpringWebBeanBlog  因为目前正在从事一个项目,项目中一个需求就是所有的功能都是插件的形式装 ...

  5. python模块time&datetime&json & picle&14.logging等

    本节大纲: 模块介绍 time &datetime模块 random os sys shutil json & picle shelve xml处理 yaml处理 configpars ...

  6. APACHE POI教程 --java应用程序用POI与Excel交互

    POI报表 --用POI与Excel交互 AURISOFT 第一章 POI简介 --Jakata Poi HSSF:纯java的Excel解决方案 在我们实际的开发中,表现层的解决方案虽然有多样,但是 ...

  7. Java中的char到底是多少个字节?

    貌似一个简单的问题(也许还真是简单的)但是却把曾经自认为弄清楚的我弄得莫名其妙 char在Java中应该是16个字节byte在Java中应该是8个字节char x = '编'; //这样是合法的,输出 ...

  8. java.lang.reflect.Constructor

    java.lang.reflect.Constructor 一.Constructor类是什么 Constructor是一个类,位于java.lang.reflect包下. 在Java反射中 Cons ...

  9. oracle中substr与instr

    在oracle中,可以使用instr函数对某个字符串进行判断,判断其是否含有指定的字符.在一个字符串中查找指定的字符,返回被查找到的指定字符的位置. 语法: Instr(sourceString,de ...

  10. c#winform选择文件,文件夹,打开指定目录方法

    private void btnFile_Click(object sender, EventArgs e) { OpenFileDialog fileDialog = new OpenFileDia ...