天天看点

php 协程 爬虫,协程(效率最快、重点)--初识协程、gevent模块、协程爬虫、协程socket(一)...

https://www.cnblogs.com/post/readauth?url=/mys6/p/10803772.html

初识协程

# 进程 启动多个进程 进程之间是由操作系统负责调用(时间片切换,人眼看似同时运行)

# 线程 启动多个线程 真正被CPU执行的最小单位实际是线程(也可形成看似同时运行并发效果,由于python语言中CPython无法多线程使用多CPU,

但其他语言多线程可使用多CPU,所以PYTHON不适合计算类程序,因为计算需要用到CPU)

# 开启一个线程 创建一个线程(一小块内存消耗》》寄存器 堆栈)

# 关闭一个线程(也需小量内存开销)

# 协程

# 本质上是一个线程

# 能够在多个任务之间(程序之间)切换来节省一些IO时间

# 协程中任务之间的切换也消耗时间,但是开销要远远小于进程线程之间的切换

# 实现并发的手段

# 一个简单模拟协程概念(两个函数之间切换)

# import time

# def consumer():

# while True:

# x = yield(生成器)

# time.sleep(1)

# print('处理了数据 :',x)

#

# def producer():

# c = consumer()

# next(c)

# for i in range(10):

# time.sleep(1)

# print('生产了数据 :',i)

# c.send(i)

#

# producer()

php 协程 爬虫,协程(效率最快、重点)--初识协程、gevent模块、协程爬虫、协程socket(一)...

# 真正的协程模块就是使用greenlet完成的切换

# from greenlet import greenlet

# def eat():

# print('eating start')

# g2.switch()

# print('eating end')

# g2.switch()

#

# def play():

# print('playing start')

# g1.switch()

# print('playing end')

# g1 = greenlet(eat)

# g2 = greenlet(play)

# g1.switch()

php 协程 爬虫,协程(效率最快、重点)--初识协程、gevent模块、协程爬虫、协程socket(一)...
php 协程 爬虫,协程(效率最快、重点)--初识协程、gevent模块、协程爬虫、协程socket(一)...

nginx负载均衡内部就用到协程(最大并发5W)

php 协程 爬虫,协程(效率最快、重点)--初识协程、gevent模块、协程爬虫、协程socket(一)...

协程和gevent模块

php 协程 爬虫,协程(效率最快、重点)--初识协程、gevent模块、协程爬虫、协程socket(一)...

协程规避IO的例子(充分利用IO操作等待时间),无需关系两个函数之间是怎么切换的

gevent模块相当与操作系统对进程的之间的切换一样,gevent是起到对协程遇到IO操作切换

php 协程 爬虫,协程(效率最快、重点)--初识协程、gevent模块、协程爬虫、协程socket(一)...
php 协程 爬虫,协程(效率最快、重点)--初识协程、gevent模块、协程爬虫、协程socket(一)...

进程是操作系统资源分配单位,线程是CPU最小的执行单位,那协程呢?(就是对线程之间切换操作)

php 协程 爬虫,协程(效率最快、重点)--初识协程、gevent模块、协程爬虫、协程socket(一)...

# from gevent import monkey;monkey.patch_all() #这里如果不导入这段,gevent是无法识别time.sleep(1)(可以识别gevent.sleep(1),但系统时间一般用time模板)

# import time

# import gevent

# import threading

# def eat():

# print(threading.current_thread().getName()) 查看虚拟线程名》》协程名,两个协程

# print(threading.current_thread()) 协程(虚拟线程)ID,不是线程ID号,虽然两个协程ID不一样,但他们是在同一线程里

# print('eating start')

# time.sleep(1)

# print('eating end')

#

# def play():

# print(threading.current_thread().getName())

# print(threading.current_thread())

# print('playing start')

# time.sleep(1)

# print('playing end')

#

# g1 = gevent.spawn(eat) # 开启一个协程

# g2 = gevent.spawn(play)

# g1.join()识别一个程序的结束

# g2.join()

# 进程和线程的任务切换右操作系统完成,不管进程或线程里代码写的什么,到了时间片轮换就切换,

#协程任务之间的切换由程序(代码)完成,只有遇到协程模块能识别的IO操作的时候,程序才会进行任务切换,实现并发的效果 如果没遇到IO操作,就不会进行任务切换,不能实现并发的效果,而是按代码顺序执行

php 协程 爬虫,协程(效率最快、重点)--初识协程、gevent模块、协程爬虫、协程socket(一)...

# 同步 和 异步

# from gevent import monkey;monkey.patch_all()

# import time

# import gevent

#

# def task(n):

# time.sleep(1)

# print(n)

#

# def sync(): # 同步方式

# for i in range(10):

# task(i)

#

# def async(): #异步方式,高网络IO情况使用这种协程方式比较好,小IO或计算类不适合用协程

# g_lst = []

# for i in range(10):

# g = gevent.spawn(task,i)

# g_lst.append(g)

# gevent.joinall(g_lst) 传入一个可迭代对象 # 等同于for g in g_lst:g.join()的效果

# sync()

# async()

# 协程 : 能够在一个线程中实现并发效果的概念

# 能够规避一些任务中的IO操作

# 在任务的执行过程中,检测到IO就切换到其他任务

# 多线程 被弱化了

# 协程 在一个线程上 提高CPU 的利用率

# 协程相比于多线程的优势 切换的效率更快

# 爬虫的例子(需要正则基础)

# 请求过程中的IO等待

php 协程 爬虫,协程(效率最快、重点)--初识协程、gevent模块、协程爬虫、协程socket(一)...

# from gevent import monkey;monkey.patch_all() 捕获IO或网络延迟

# import gevent

# from urllib.request import urlopen # 内置的模块

# def get_url(url):

# response = urlopen(url)

# content = response.read().decode('utf-8')

# return len(content)

#

# g1 = gevent.spawn(get_url,'http://www.baidu.com')

# g2 = gevent.spawn(get_url,'http://www.sogou.com')

# g3 = gevent.spawn(get_url,'http://www.taobao.com')

# g4 = gevent.spawn(get_url,'http://www.hao123.com')

# g5 = gevent.spawn(get_url,'http://www.cnblogs.com')

# gevent.joinall([g1,g2,g3,g4,g5]) 识别所有代码结束

# print(g1.value)

# print(g2.value)一起打印(并发效果)

# print(g3.value)

# print(g4.value)

# print(g5.value)

# ret = get_url('http://www.baidu.com')

# print(ret)

协程socket

server端

from gevent import monkey;monkey.patch_all()

import socket

import gevent

def talk(conn):

conn.send(b'hello')

print(conn.recv(1024).decode('utf-8'))

conn.close()

sk = socket.socket() sk.bind(('127.0.0.1',8080))

sk.listen()

while True: #异步

conn,addr = sk.accept()

gevent.spawn(talk,conn)

sk.close()

client端

import socket

sk = socket.socket()

sk.connect(('127.0.0.1',8080))

print(sk.recv(1024))

msg = input('>>>').encode('utf-8')

sk.send(msg)

sk.close()

php 协程 爬虫,协程(效率最快、重点)--初识协程、gevent模块、协程爬虫、协程socket(一)...
php 协程 爬虫,协程(效率最快、重点)--初识协程、gevent模块、协程爬虫、协程socket(一)...