线程和进程
1.进程是资源单位, 每一个进程至少要有一个线程
2.线程是执行单位
3.启动每一个程序默认都会有一个主线程
# 线程, 进程
# 进程是资源单位, 每一个进程至少要有一个线程
# 线程是执行单位
# 启动每一个程序默认都会有一个主线程
# def func():
# for i in range(1000):
# print("func", i)
#
#
# if __name__ == '__main__':
# func()
# for i in range(1000):
# print("main", i)
# 多线程, 创建一个线程类
from threading import Thread
# def func():
# for i in range(1000):
# print("func", i)
#
#
# if __name__ == '__main__':
# t = Thread(target=func) # 创建线程并给线程安排任务
# t.start() # 多线程状态为可以开始工作状态, 具体的执行时间由CPU决定
#
# for i in range(1000):
# print("main", i)
class MyThread(Thread):
# 这个函数是固定的, 当线程被执行的时候, 被执行的就是run()
def run(self):
for i in range(1000):
print("子线程", i)
if __name__ == '__main__':
t = MyThread()
# t.run() # 方法的调用了. -> 单线程
# 开启线程
t.start()
for i in range(1000):
print("主线程", i)
多进程的基础代码
# 多进程的代码基础
from multiprocessing import Process
from threading import Thread
# def func():
# for i in range(1000):
# print("子进程", i)
#
#
# if __name__ == '__main__':
# p = Process(target=func)
# p.start()
# for i in range(1000):
# print("主进程", i)
def func(name):
for i in range(1000):
print(name, i)
if __name__ == '__main__':
t1 = Thread(target=func, args=("周杰林",))
t1.start()
for i in range(1000):
print(i)
t2 = Thread(target=func, args=("王力宏",))
t2.start()
线程池和进程池的基础
# 线程池和进程池的基础
from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor
def fn(name):
for i in range(1000):
print(name, i)
if __name__ == '__main__':
# 创建线程池
with ThreadPoolExecutor(50) as t:
for i in range(100):
t.submit(fn, name=f"线程{i}\n")
# 等待线程池中的任务全部执行完毕。 才能继续执行(守护)
print("123")
异步的导入
# import time
#
#
# def func():
# print("我爱黎明")
# time.sleep(3) # 让当前的线程处于阻塞状态. CPU是不为我工作的
# print("我真的爱黎明")
#
#
# if __name__ == '__main__':
# func()
#
# """
# # input() 程序也是处于阻塞状态
# # requests.get(bilibili) 在网络请求返回数据之前, 程序也是处于阻塞状态的
# # 一般情况下, 当程序处于 IO操作的时候. 线程都会处于阻塞状态
#
# # 协程: 当程序遇见了IO操作的时候. 可以选择性的切换到其他任务上.
# # 在微观上是一个任务一个任务的进行切换. 切换条件一般就是IO操作
# # 在宏观上,我们能看到的其实是多个任务一起在执行
# # 多任务异步操作
#
# # 上方所讲的一切. 都是在单线程的条件下
# """
# python编写协程的程序
# 导入异步操作的包
import asyncio
import time
# async def func():
# print("你好啊, 我叫赛利亚")
#
#
# if __name__ == '__main__':
# g = func() # 此时的函数是异步协程函数. 此时函数执行得到的是一个协程对象
# # print(g)
# asyncio.run(g) # 协程程序运行需要asyncio模块的支持
# async def func1():
# print("你好啊, 我叫潘金莲")
# # time.sleep(3) # 当程序出现了同步操作的时候. 异步就中断了
# await asyncio.sleep(3) # 异步操作的代码
# print("你好啊, 我叫潘金莲")
#
#
# async def func2():
# print("你好啊, 我叫王建国")
# # time.sleep(2)
# await asyncio.sleep(2)
# print("你好啊, 我叫王建国")
#
#
# async def func3():
# print("你好啊, 我叫李雪琴")
# await asyncio.sleep(4)
# print("你好啊, 我叫李雪琴")
#
#
# if __name__ == '__main__':
# f1 = func1()
# f2 = func2()
# f3 = func3()
# tasks = [
# f1, f2, f3
# ]
# t1 = time.time()
# # 一次性启动多个任务(协程)
# asyncio.run(asyncio.wait(tasks))
# t2 = time.time()
# print(t2 - t1)
async def func1():
print("你好啊, 我叫潘金莲")
await asyncio.sleep(3)
print("你好啊, 我叫潘金莲")
async def func2():
print("你好啊, 我叫王建国")
await asyncio.sleep(2)
print("你好啊, 我叫王建国")
async def func3():
print("你好啊, 我叫李雪琴")
await asyncio.sleep(4)
print("你好啊, 我叫李雪琴")
async def main():
# 第一种写法
# f1 = func1()
# await f1 # 一般await挂起操作放在协程对象前面
# 第二种写法(推荐)
tasks = [
# py3.8以后加上asyncio.create_task()
asyncio.create_task(func1()),
asyncio.create_task(func2()),
asyncio.create_task(func3())
]
await asyncio.wait(tasks)
if __name__ == '__main__':
t1 = time.time()
# 一次性启动多个任务(协程)
asyncio.run(main())
t2 = time.time()
print(t2 - t1)
# # 在爬虫领域的应用
# async def download(url):
# print("准备开始下载")
# await asyncio.sleep(2) # 网络请求 requests.get()
# print("下载完成")
#
#
# async def main():
# urls = [
# "http://www.baidu.com",
# "http://www.bilibili.com",
# "http://www.163.com"
# ]
#
# # 准备异步协程对象列表
# tasks = []
# for url in urls:
# d = asycio.create_task(download(url))
# tasks.append(d)
#
# # tasks = [asyncio.create_task(download(url)) for url in urls] # 这么干也行哦~
#
# # 一次性把所有任务都执行
# await asyncio.wait(tasks)
#
# if __name__ == '__main__':
# asyncio.run(main())
项目实战
# requests.get() 同步的代码 -> 异步操作aiohttp
# pip install aiohttp
import asyncio
import aiohttp
urls = [
"http://kr.shanghai-jiuxin.com/file/2020/1031/191468637cab2f0206f7d1d9b175ac81.jpg",
"http://kr.shanghai-jiuxin.com/file/2020/1031/563337d07af599a9ea64e620729f367e.jpg",
"http://kr.shanghai-jiuxin.com/file/2020/1031/774218be86d832f359637ab120eba52d.jpg"
]
async def aiodownload(url):
# 发送请求.
# 得到图片内容
# 保存到文件
# rsplit()函数是第一个参数从右面开始进行切割,最后是一个列表的格式
name = url.rsplit("/", 1)[1]
async with aiohttp.ClientSession() as session:
# resp = requests.get()
# 可以自己去学习一个模块, aiofiles
async with session.get(url) as resp:
# 创建文件
with open(name, mode="wb") as f:
# 读取内容是异步的. 需要await挂起, resp.text()
f.write(await resp.content.read())
print(name, "搞定")
async def main():
tasks = []
for url in urls:
tasks.append(aiodownload(url))
await asyncio.wait(tasks)
if __name__ == '__main__':
# asyncio.run(main())
# 会有如下的问题
# raise RuntimeError('Event loop is closed')
# RuntimeError: Event loop is closed
# Exception ignored in: <function _ProactorBasePipeTransport.__del__ at 0x000002712CEB0EE0>
loop = asyncio.get_event_loop()
loop.run_until_complete(main())