zoukankan      html  css  js  c++  java
  • py 的 第 35 天

     1. socket 发送请求

    b'GET /s?wd=alex HTTP/1.0 host:www.baidu.com

    这就是固定格式,b字节,get 后必须跟空格然后/ s?wd=alex是百度固定的后缀 后面再来空格 HTTP/1.0 这也是固定格式 后面再带个host:www.baidu.com同固定格式 两个结尾

    2.解除阻塞

    import socket
    
    client = socket.socket()
    client.setblocking(False) # 将原来阻塞的位置变成非阻塞(报错)
    # 百度创建连接: 阻塞
    
    try:
        client.connect(('www.baidu.com',80)) # 执行了但报错了
    except BlockingIOError as e:
        pass
    
    # 检测到已经连接成功
    
    # 问百度我要什么?
    client.sendall(b'GET /s?wd=alex HTTP/1.0
    host:www.baidu.com
    
    ')
    
    # 我等着接收百度给我的回复
    chunk_list = []
    while True:
        chunk = client.recv(8096) # 将原来阻塞的位置变成非阻塞(报错)
        if not chunk:
            break
        chunk_list.append(chunk)
    
    body = b''.join(chunk_list)
    print(body.decode('utf-8'))
    

    3 io多路复用,检测多个socket是否已经发生变化(是否已经连接成功,是否可以获得数据)可读/可写

    import socket
    import select
    
    
    
    client1 = socket.socket()
    client1.setblocking(False) # 百度创建连接: 非阻塞
    
    try:
        client1.connect(('www.baidu.com',80))
    except BlockingIOError as e:
        pass
    
    
    client2 = socket.socket()
    client2.setblocking(False) # 百度创建连接: 非阻塞
    try:
        client2.connect(('www.sogou.com',80))
    except BlockingIOError as e:
        pass
    
    
    client3 = socket.socket()
    client3.setblocking(False) # 百度创建连接: 非阻塞
    try:
        client3.connect(('www.oldboyedu.com',80))
    except BlockingIOError as e:
        pass
    
    socket_list = [client1,client2,client3]
    conn_list = [client1,client2,client3]
    
    while True:
        rlist,wlist,elist = select.select(socket_list,conn_list,[],0.005) #select检测里面的数据有没有变化,如果有人给他发数据,就会检测到变化   他会接收3个元组   但凡rlist有值就是数据返回回来了,但凡wlist返回回来就是连接成功
        # wlist中表示已经连接成功的socket对象
        for sk in wlist:
            if sk == client1:
                sk.sendall(b'GET /s?wd=alex HTTP/1.0
    host:www.baidu.com
    
    ')
            elif sk==client2:
                sk.sendall(b'GET /web?query=fdf HTTP/1.0
    host:www.sogou.com
    
    ')
            else:
                sk.sendall(b'GET /s?wd=alex HTTP/1.0
    host:www.oldboyedu.com
    
    ')
            conn_list.remove(sk)
        for sk in rlist:
            chunk_list = []     #故技重施
            while True:
                try:
                    chunk = sk.recv(8096)
                    if not chunk:
                        break
                    chunk_list.append(chunk)
                except BlockingIOError as e:
                    break
            body = b''.join(chunk_list)
            # print(body.decode('utf-8'))
            print('------------>',body)
            sk.close()
            socket_list.remove(sk)
        if not socket_list:
            break

     

     4.twisted,基于事件循环实现的异步非阻塞框架   非阻塞:不等待

    异步:执行完某个任务后自用调用我给他的函数。  自动下载完回调自己的函数,谁都不等待谁

    1.socket 默认是阻塞的 阻塞在连接时,和接收时

    2. setblocking(False)   把他变成非阻塞的

     3。io多路复用作用为,检测多个socket是否发生了变化   实际是操作系统检测socket是否发生变化,有三种模式

    select:限制为1024个socket;内部检测是用的循环

    poll:不限个数  但还是内部循环(水平触发)

    epoll:不限个数,会调方式(边缘触发)

     python中的模块:

      select.select

      select.epoll   win没有

    4。提高并发的方案

      多进程

      多线程

      单线程异步非阻塞模块(twisted)scrapy框架(单线程完成并发)

    5.异步非阻塞

      非阻塞,不等待,比如创建socket对某个地址进行connect,获取接收数据recv时默认都会等待连接成功,或接收到数据,才执行后续操作,如果设置成setblocking(False)以上两个过程都不再等待但是回报blockingIOError的错,只要捕获即可,

      异步,执行完成之后自动执行回调函数或自动执行某些操作(通知)。

        比如做爬虫中向某个地址xxx发送请求,当请求执行完成之后自动执行回调函数。

    6.同步阻塞

      阻塞:等

      同步:按照顺序逐步执行

    io多路复用,和 

     7.在别人不改变的时候,你还想请求完成,只能自己改变

    协程

      进程,操作系统中存在;

      线程,操作系统中存在;

      协程,是由程序员创造出来的一个不是真实存在的东西;

      协程,是微线程。对一个线程进行分片,使得线程在代码块之间进行来回切换执行,而不是在原来逐行执行,单纯协程没用,甚至性能降低 

    import greenlet
    
    
    def f1():
        print(11)
        gr2.switch()
        print(22)
        gr2.switch()
    
    
    def f2():
        print(33)
        gr1.switch()
        print(44)
    
    
    # 协程 gr1
    gr1 = greenlet.greenlet(f1)
    # 协程 gr2
    gr2 = greenlet.greenlet(f2)
    
    gr1.switch()             微协程写完了
    

     协程+遇到IO就切换=>牛逼起来了

    from gevent import monkey
    monkey.patch_all() # 以后代码中遇到IO都会自动执行greenlet的switch进行切换
    import requests
    import gevent       #上面这些一定要写
    
    
    def get_page1(url):
        ret = requests.get(url)
        print(url,ret.content)
    
    
    gevent.joinall([
        gevent.spawn(get_page1, 'https://www.python.org/'), # 协程1
        gevent.spawn(get_page1, 'https://www.yahoo.com/'),  # 协程2
        gevent.spawn(get_page1, 'https://github.com/'),     # 协程3
    ])
    

     协程也可以称之为 微线程,就是开发者控制线程执行流程,控制先执行某段代码,然后再切换到另外函数执行代码。。。来回切换。

    协程不一定可以提高并发,协程自己本身无法提高啊并发,(甚至会降低)。协程+IO切换性能提高。

    进程线程区别。

    进程是计算机资源分配的最小单元,主要做数据隔离,线程是工作的最小单元,主要工作的就是线程,一个进程里可以有多个线程,一个应用程序里可以有多个进程,应用场景在其他语言里基本没有进程概念,都是用的线程,在python里io操作多的时候,用线程,计算密集型的时候,用进程,因为py有GIL锁,锁住了一个进程中同一时刻只能调用一个线程,无法把cpu完全使用,多线程io不占cpu,程序员为了优化代码,创造了协程,本身不存在,协程本身让人为控制,先执行这个后执行那个,本来没用配合io就有用了,遇到io就执行别的,遇到i o切换到别的地方执行了,把线程分片了,就是让线程一直不停,一直工作,遇到io就切换到别的地方工作,io操作回来的之后再切回来,这点区别吧,py用协程的时候,要用到 greenlet 模块,实现io加协程自动切换的模块gevent

     4.单线程提供并发:

      协程+io切换  gevent

      基于事件循环的异步非阻塞框架:twisted

  • 相关阅读:
    联想Thinkpad L460安装Win7 64位
    2019牛客暑期多校训练营(第六场)E 构造、原图是补图的同构图
    网络流24题 P2766 最长不下降子序列问题
    The 2019 ICPC China Nanchang National Invitational and International Silk-Road Programming Contest B、H
    P4781 拉格朗日插值
    P4717 快速沃尔什变换FWT 模板题
    2019CCPC-江西省赛C题 HDU6569 GCD预处理+二分
    Gym 101917 E 简单计算几何,I 最大流
    51 Nod 1238 最小公倍数之和 V3 杜教筛
    51Nod 1237 最大公约数之和 V3 杜教筛
  • 原文地址:https://www.cnblogs.com/Mrszhao/p/9647154.html
Copyright © 2011-2022 走看看