requests模块的介绍
requests的作用
通过python来模拟请求网址
一个模拟请求由以下四个部分组成
- url
- method
- body
- headers
模拟请求百度
没有安装requests库的同学, 在当前python环境下执行以下语句安装第三方库 pip install requests
import requests def request_baidu(): url = "https://www.baidu.com/" # body = "" headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36" } response = requests.get(url=url, headers=headers) print(response.text)
理解多线程和多进程
什么是进程?什么是线程?
- 进程: 可以简单地认为是一个程序. 进程是操作系统分配资源的最小单位.
- 线程: 一个进程可以有多个线程, 每个线程可以独立完成一些任务. 线程是操作系统进行运算调度的最小单位.
多线程demo
from threading import Thread for i in range(10): # 只是创建了线程对象 t = Thread(target=request_baidu) # 启动线程 t.start()
多进程demo
from multiprocessing import Process for i in range(10): # 只是创建了进程对象 p = Process(target=request_baidu) # 启动进程 p.start()
多线程
等待任务完成后回到主进程
通过调用
Thread
对象的join
方法# 保存当前thread对象 thread_array = [] for i in range(10): t = Thread(target=request_baidu, args=(i, )) thread_array.append(t) t.start() # 调用thread对象join接口, 等待任务完成后回到主进程 for t in thread_array: t.join() print("done!")
如何拿到返回结果
赋值到全局变量当中, 添加到可变对象之中
result = [] def request_baidu(index): ... result.append(response) if __name__ == "__main__": thread_array = [] for i in range(10): t = Thread(target=request_baidu, args=(i, )) thread_array.append(t) t.start() for t in thread_array: t.join() print("done!") print(result)
多进程
等待任务完成后回到主进程
通过调用
Process
对象的join
方法如何拿到返回结果
无法通过全局变量存储返回结果.
多进程相当于启动了多个程序, 共同执行了同一份代码, 他们之间的内存地址完全不一样
import requests import time from threading import Thread from multiprocessing import Process result = [] print(f"主进程result内存地址: {id(result)}") def request_baidu(index): time.sleep(2) url = "https://www.baidu.com/" # body = "" headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36" } response = requests.get(url=url, headers=headers) print(f"当前请求序号: {index}, 返回结果状态码: {response.status_code}") print(f"子进程result内存地址: {id(result)}") result.append(response) # 如果没有判断入口代码段if __name__ == "__main__", 多进程程序会报错 # 原因是windows和pycharm的进程阻塞带来的问题 if __name__ == "__main__": process_array = [] for i in range(10): p = Process(target=request_baidu, args=(i, )) process_array.append(p) p.start() for p in process_array: p.join() print("done!") print(result)
多进程和多线程的异同点
相同点
都是对
cpu
工作时间段的描述, 只是颗粒度不同.简单地说就是多进程和多线程都会调用
cpu
资源的, 但是进程可以启动多个线程去执行.- 在
linux
内核态不区分进程和线程
不同点
- 进程有自己的独立地址空间, 建立数据表来维护代码段, 堆栈段和数据段, 而线程共享进程中的资源, 使用相同的地址空间, 所以线程间的切换快得多.
- 因为线程共享进程的全局变量, 静态变量等对象, 线程间的通信更为方便, 而进程间的通信更加复杂, 需要以
ipc
的方式进行. - 多进程要比多线程要健壮. 进程之间一般不会相互影响, 而多线程有一条线程崩溃, 会导致整个进程跟着发生崩溃或者无法正常退出等.
全局解释器锁(GIL)
计算密集型
主要占用
cpu
资源IO密集型
IO
就是input output
, 需要等待的一些任务- 网络请求会有网络延迟
- 和数据库交互需要等待数据库查询事件
- 读写硬盘
多进程在处理计算密集型程序的时候比多线程块
由于全局解释器锁的存在, 一个进程下, 只允许一个线程执行
Python
程序的字节码(当前代码文件的二进制表示).简单地说, 创建的10个线程其实在争夺一个
cpu
资源. 但是遇到io
操作会让渡cpu
资源.如何绕过GIL?
- 将多线程方法改为多进程
- 将计算密集型任务转移给C扩展.
- 分布式计算引擎
spark
,Apache
- 使用
PyPy
解释器, 工业上几乎没人这么用, 因为PyPy
并不成熟.
Comment here is closed