回顾:
进程
一个程序需要运行所需的资源的集合
每个进程数据是独立的
每个进程里至少有一个线程
进程里可以有多个线程
线程数据是共享的 一个进程的多个线 6程可以充分利用多核cpu multiprocessing
pipe
queue
实现的是进程间的数据传递,通信 manager 实现了多进程间的数据共享 进程间共享数据的代价是高昂的,所以要尽量避免进程间的数据共享 线程间的数据本来就是共享的
线程要修改同一份数据,必须加锁,互斥锁mutex
event
线程间交互 生产者消费者模型
解耦 (降低进程间的依赖性)
提高程序运行效率 queue
FIFO
LIFO
优先级queue
适用场景:
线程:
I/O密集型(I/O不占用cpu),socket 爬虫 web
进程:cpu运算密集型,金融分析
  1. Gevent协程
    1. 协程

      协程,又称微线程,纤程。英文名Coroutine。一句话说明什么是线程:协程是一种用户态的轻量级线程。

      协程拥有自己的寄存器上下文和栈。协程调度切换时,将寄存器上下文和栈保存到其他地方,在切回来的时候,恢复先前保存的寄存器上下文和栈。因此:

      协程能保留上一次调用时的状态(即所有局部状态的一个特定组合),每次过程重入时,就相当于进入上一次调用的状态,换种说法:进入上一次离开时所处逻辑流的位置。

      协程的好处:

      • 无需线程上下文切换的开销
      • 无需原子操作锁定及同步的开销
        •   "原子操作(atomic operation)是不需要synchronized",所谓原子操作是指不会被线程调度机制打断的操作;这种操作一旦开始,就一直运行到结束,中间不会有任何 context switch (切换到另一个线程)。原子操作可以是一个步骤,也可以是多个操作步骤,但是其顺序是不可以被打乱,或者切割掉只执行部分。视作整体是原子性的核心。
      • 方便切换控制流,简化编程模型
      • 高并发+高扩展性+低成本:一个CPU支持上万的协程都不是问题。所以很适合用于高并发处理。

      缺点:

      • 无法利用多核资源:协程的本质是个单线程,它不能同时将 单个CPU 的多个核用上,协程需要和进程配合才能运行在多CPU上.当然我们日常所编写的绝大部分应用都没有这个必要,除非是cpu密集型应用。
      • 进行阻塞(Blocking)操作(如IO时)会阻塞掉整个程序
    2. 协程标准定义,即符合什么条件就能称之为协程:

      1. 必须在只有一个单线程里实现并发
      2. 修改共享数据不需加锁
      3. 用户程序里自己保存多个控制流的上下文栈
      4. 一个协程遇到IO操作自动切换到其它协程

       

    3. Greenlet

      1. greenlet是一个用C实现的协程模块,相比与python自带的yield,它可以使你在任意函数之间随意切换,而不需把这个函数先声明为generator

         # -*- coding:utf-8 -*-
        
         from greenlet import greenlet
        
         def test1():
        print(12)
        gr2.switch()
        print(34)
        gr2.switch() def test2():
        print(56)
        gr1.switch()
        print(78) gr1 = greenlet(test1)
        gr2 = greenlet(test2)
        gr1.switch()
    4. Gevent

      1. Gevent 是一个第三方库,可以轻松通过gevent实现并发同步或异步编程,在gevent中用到的主要模式是Greenlet, 它是以C扩展模块形式接入Python的轻量级协程。 Greenlet全部运行在主程序操作系统进程的内部,但它们被协作式地调度。

         import gevent
        
         def func1():
        print('\033[31;1m李闯在跟海涛搞...\033[0m')
        gevent.sleep(2)
        print('\033[31;1m李闯又回去跟继续跟海涛搞...\033[0m') def func2():
        print('\033[32;1m李闯切换到了跟海龙搞...\033[0m')
        gevent.sleep(1)
        print('\033[32;1m李闯搞完了海涛,回来继续跟海龙搞...\033[0m') gevent.joinall([
        gevent.spawn(func1),
        gevent.spawn(func2),
        #gevent.spawn(func3),
        ])
      2. 同步与异步的性能区别
        import gevent
        
        def task(pid):
        """
        Some non-deterministic task
        """
        gevent.sleep(0.5)
        print('Task %s done' % pid) def synchronous():
        for i in range(1,10):
        task(i) def asynchronous():
        threads = [gevent.spawn(task, i) for i in range(10)]
        gevent.joinall(threads) print('Synchronous:')
        synchronous() print('Asynchronous:')
        asynchronous()
  2. Select\Poll\Epoll异步IO与事件驱动

    select 多并发socket 例子

    server

    

 #_*_coding:utf-8_*_
__author__ = 'Alex Li' import select
import socket
import sys
import queue server = socket.socket()
server.setblocking(0) server_addr = ('localhost',10000) print('starting up on %s port %s' % server_addr)
server.bind(server_addr) server.listen(5) inputs = [server, ] #自己也要监测呀,因为server本身也是个fd
outputs = [] message_queues = {} while True:
print("waiting for next event...") readable, writeable, exeptional = select.select(inputs,outputs,inputs) #如果没有任何fd就绪,那程序就会一直阻塞在这里 for s in readable: #每个s就是一个socket if s is server: #别忘记,上面我们server自己也当做一个fd放在了inputs列表里,传给了select,如果这个s是server,代表server这个fd就绪了,
#就是有活动了, 什么情况下它才有活动? 当然 是有新连接进来的时候 呀
#新连接进来了,接受这个连接
conn, client_addr = s.accept()
print("new connection from",client_addr)
conn.setblocking(0)
inputs.append(conn) #为了不阻塞整个程序,我们不会立刻在这里开始接收客户端发来的数据, 把它放到inputs里, 下一次loop时,这个新连接
#就会被交给select去监听,如果这个连接的客户端发来了数据 ,那这个连接的fd在server端就会变成就续的,select就会把这个连接返回,返回到
#readable 列表里,然后你就可以loop readable列表,取出这个连接,开始接收数据了, 下面就是这么干 的 message_queues[conn] = queue.Queue() #接收到客户端的数据后,不立刻返回 ,暂存在队列里,以后发送 else: #s不是server的话,那就只能是一个 与客户端建立的连接的fd了
#客户端的数据过来了,在这接收
data = s.recv(1024)
if data:
print("收到来自[%s]的数据:" % s.getpeername()[0], data)
message_queues[s].put(data) #收到的数据先放到queue里,一会返回给客户端
if s not in outputs:
outputs.append(s) #为了不影响处理与其它客户端的连接 , 这里不立刻返回数据给客户端 else:#如果收不到data代表什么呢? 代表客户端断开了呀
print("客户端断开了",s) if s in outputs:
outputs.remove(s) #清理已断开的连接 inputs.remove(s) #清理已断开的连接 del message_queues[s] ##清理已断开的连接 for s in writeable:
try :
next_msg = message_queues[s].get_nowait() except queue.Empty:
print("client [%s]" %s.getpeername()[0], "queue is empty..")
outputs.remove(s) else:
print("sending msg to [%s]"%s.getpeername()[0], next_msg)
s.send(next_msg.upper()) for s in exeptional:
print("handling exception for ",s.getpeername())
inputs.remove(s)
if s in outputs:
outputs.remove(s)
s.close() del message_queues[s]

client

 #_*_coding:utf-8_*_
__author__ = 'Alex Li' import socket
import sys messages = [ b'This is the message. ',
b'It will be sent ',
b'in parts.',
]
server_address = ('localhost', 10000) # Create a TCP/IP socket
socks = [ socket.socket(socket.AF_INET, socket.SOCK_STREAM),
socket.socket(socket.AF_INET, socket.SOCK_STREAM),
] # Connect the socket to the port where the server is listening
print('connecting to %s port %s' % server_address)
for s in socks:
s.connect(server_address) for message in messages: # Send messages on both sockets
for s in socks:
print('%s: sending "%s"' % (s.getsockname(), message) )
s.send(message) # Read responses on both sockets
for s in socks:
data = s.recv(1024)
print( '%s: received "%s"' % (s.getsockname(), data) )
if not data:
print(sys.stderr, 'closing socket', s.getsockname() )
复制代码

selectors模块

 import selectors
import socket sel = selectors.DefaultSelector() def accept(sock, mask):
conn, addr = sock.accept() # Should be ready
print('accepted', conn, 'from', addr)
conn.setblocking(False)
sel.register(conn, selectors.EVENT_READ, read) def read(conn, mask):
data = conn.recv(1000) # Should be ready
if data:
print('echoing', repr(data), 'to', conn)
conn.send(data) # Hope it won't block
else:
print('closing', conn)
sel.unregister(conn)
conn.close() sock = socket.socket()
sock.bind(('localhost', 10000))
sock.listen(100)
sock.setblocking(False)
sel.register(sock, selectors.EVENT_READ, accept) while True:
events = sel.select()
for key, mask in events:
callback = key.data
callback(key.fileobj, mask)

Python之路,day11-Python基础的更多相关文章

  1. Python之路,Day4 - Python基础4 (new版)

    Python之路,Day4 - Python基础4 (new版)   本节内容 迭代器&生成器 装饰器 Json & pickle 数据序列化 软件目录结构规范 作业:ATM项目开发 ...

  2. Python之路,Day1 - Python基础1

    本节内容 Python介绍 发展史 Python 2 or 3? 安装 Hello World程序 变量 用户输入 模块初识 .pyc是个什么鬼? 数据类型初识 数据运算 表达式if ...else语 ...

  3. Python之路,Day1 - Python基础1(转载Alex)

    本节内容 Python介绍 发展史 Python 2 or 3? 安装 Hello World程序 变量 用户输入 模块初识 .pyc是个什么鬼? 数据类型初识 数据运算 表达式if ...else语 ...

  4. Python之路,Day1 - Python基础1 --转自金角大王

    本节内容 Python介绍 发展史 Python 2 or 3? 安装 Hello World程序 变量 用户输入 模块初识 .pyc是个什么鬼? 数据类型初识 数据运算 表达式if ...else语 ...

  5. Python之路,Day1 - Python基础1 介绍、基本语法、流程控制

    本节内容 1.python介绍 2.发展史 3.python 2.x or python 3.x ? 4.python 安装 5.第一个程序 Hello World 程序 6.变量 7.用户输入 8. ...

  6. Python之路:Python简介

    Python前世今生 python的创始人为吉多·范罗苏姆(Guido van Rossum).1989年的圣诞节期间他为了在阿姆斯特丹打发时间,决心开发一个新的脚本解释程序,作为ABC语言的一种继承 ...

  7. Python之路:Python操作 RabbitMQ、Redis、Memcache、SQLAlchemy

    Memcached Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载.它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提高动态.数据库驱动网站的速度 ...

  8. Python之路-初识python及环境搭建与测试(Python安装、Anaconda安装、PyCharm安装)

    一.认识Python 起源 Python的作者是著名的“龟叔”Guido van Rossum,他希望有一种语言,这种语言能够像C语言那样,能够全面调用计算机的功能接口,又可以像shell那样,可以轻 ...

  9. Python之路,Day8 - Python基础 面向对象高级进阶与socket基础

    类的成员 类的成员可以分为三大类:字段.方法和属性 注:所有成员中,只有普通字段的内容保存对象中,即:根据此类创建了多少对象,在内存中就有多少个普通字段.而其他的成员,则都是保存在类中,即:无论对象的 ...

  10. python之路:Day01 --- Python基础1

    本节内容 1.Python介绍 2.发展史 3.变量 4.用户输入 5.表达式 if...else语句 6.表达式 for 循环 7.表达式 while 循环 8.模块初识 9.数据类型初识 10.数 ...

随机推荐

  1. web.config 配置

    一.认识Web.config文件   Web.config 文件是一个xml文本文件,它用来储存 asp.NET Web 应用程序的配置信息(如最常用的设置asp.NET Web 应用程序的身份验证方 ...

  2. ThinkPHP(3)SQL查询语句

    ThinkPHP中对查询语句,包含了基本的查询方式.表达方式.快速查询.区间查询.组合查询.SQL查询.动态查询和子查询. 一.查询方式 ThinkPHP提供了三种基本的查询方式:字符串条件查询.索引 ...

  3. Java学习1 - java 历史

    Sun的Java语言开发小组成立于1991年,其目的是开拓消费类电子产品市场,例如:交互式电视,烤面包箱等.Sun内部人员把这个项目称为 Green,那时World Wide Web还在图纸上呢.该小 ...

  4. Unity Ugui射线坐标转换总结

    世界空间中的点坐标转换到屏幕坐标: screenPos = RectTransformUtility.WorldToScreenPoint(cam, worldPos.transform.positi ...

  5. # mysql -u root -p -bash: mysql: command not found

    [root@jboss ~]# mysql -u root -p-bash: mysql: command not found 需要安装mysql # yum install mysql之后就行 了

  6. 安装Eclipse环境变量的配置,

    window7系统下的 步骤:    第一步:先安装JDK(记住你安装的位置)我安装在D:\Program Files\Java           目录下. 第二步:JDK安装好后,配置环境变量(重 ...

  7. core Bluetooth(蓝牙4.0)

    蓝牙4.0以低功耗著称,一般也叫BLE(Bluetooth Low Energy). 目前主要应用的场景有:智能家居.运动手环和室内导航等. 利用core Bluetooth框架可以实现苹果设备与第三 ...

  8. phonegap android 开发环境搭建

    1.下载JDK并安装   http://www.oracle.com/technetwork/java/javase/downloads/index-jsp-138363.html 配置环境变量   ...

  9. Centeros7 环境相关问题

    服务处理命令 systemctl start mariadb #启动MariaDB systemctl stop mariadb #停止MariaDB systemctl restart mariad ...

  10. wdcp的安装方法与常见问题

    wdcp(WDlinux Control Panel)是一套用PHP开发的Linux服务器管理系统,通过面板来操作可以彻底放弃用ssh 命令来操作的繁琐,让Linux服务器系统变得更容易使用,可以在线 ...