python基础
进程&线程
进程是一组资源的集合,运行一个系统就是打开了一个进程,如果同时打开了两个记事本就是开启了两个进程,进程是一个笼统的概念,进程中由线程干活工作,由进程统一管理
一个进程至少有一个线程,如果没有,进程也就没有了,线程分为主线程,子线程,而主线程负责调度,支配子线程运行,在代码运行时,主线程分配子线程去干活,而主线程分配之后继续执行后面代码,这时需要我们join一个,主线程等待子线程全部运行完之后,再运行后面代码
单线程 系统默认就起好一个进程,也就是起了一个进程,一个线程
import time # 单线程 时间叠加了,运行速度会变慢 start = time.time() def run():time.sleep(5)print("over") run() run() end = time.time() all_time = end - start print(all_time)
多线程下载网页
# 单线程下载网页 import threading, requests def downloads(url, file_name):res = requests.get(url)with open(file_name, 'wb') as wf:wf.write(res.content) url = {'rainbol1': 'https://www.cnblogs.com/RainBol/','rainbol2': 'https://www.cnblogs.com/RainBol/'} for file_name, url in url.items():t1 = threading.Thread(target=downloads,args=(url, file_name)) # target指定一个线程让它来帮助我执行,args执行target中的参数,只有一个用args=(url,)t1.start() # t1.start启动一个线程t1.join() # 等待子线程工作完毕,主线程再继续运行
多线程 一个进程下面有多个线程
# 由于线程分为主线程和子线程,所以我们要考虑他们之间的同步 # 方法1 for循环实现 import threading, time def run1():time.sleep(5)print("over") start = time.time() list1 = [] # 定义一个list for i in range(20): # 定义要开启20个线程t1 = threading.Thread(target=run1)t1.start()list1.append(t1) # 添加一个子线程到列表中 for t1 in list1: # 主线程走到这一步子线程都在执行time.sleep()方法,如果继续执行就代码就会走完,所以要等待所有子线程全部运行完毕 t1.join() end = time.time() print(end - start)
# 方法2 while循环实现 import threading, time def run1():time.sleep(5)print("over") start = time.time() for j in range(20): # 定义要开启20个线程t1 = threading.Thread(target=run1)t1.start() while threading.activeCount() != 1: # 如果只有一个线程的时候说明只有一个主线程了,此时循环结束,执行后面代码,否则继续循环pass end = time.time() print(end - start)
# 方式3 class Mythread(threading.Thread):def run(self):#方法必须叫runtime.sleep(5)print("over") for k in range(20):res = Mythread()res.start()#调用必须叫start
守护线程
如果你想等待子线程完成再退出,那就什么都不用写,或者显示地调用thread.setDaemon(False),设置daemon的值为false。新的子线程会继承父线程的daemon标志。整个Python会在所有的非守护线程退出后才会结束,即进程中没有非守护线程存在的时候才结束。
import time,threading #守护线程 def shouhu():time.sleep(5)print("555") for l in range(10):res = threading.Thread(target=shouhu)res.setDaemon(True)#定义守护线程,当定义了这句话表示开启守护线程 res.start() print("守护线程结束")
锁
多个线程同时操作同一个数据的时候一定要加锁
import threading# 锁,记得加锁完一定要解锁,不然出现死锁现象 num = 0 lock = threading.Lock() # 实例化一把锁 def aaa():global numlock.acquire() # 加锁num += 1lock.release() # 解锁 #或者两者一样#with lock:
#num +=1 for i in range(100):t = threading.Thread(target=aaa)t.start() while threading.activeCount() != 1:pass print(num)
在python2中一定要加锁,python3中会自动加锁解锁,但是为了规范还是加上比较好
多进程 多个进程,每个进程下面只有一个线程工作
狭隘的来说进程是根据计算机的cpu颗粒数来算的,我们通常做性能测试可以模拟1000个线程,那是cpu在做上下文切换,实际上4核cpu也就是同时只能运行4个线程,我们肉眼根本看不出来误以为计算机开了1000个并发.所以说使用进程的多少取决于你使用的cpu
而python在语言设计上由于GIL全局解释器锁,只能用cpu的一个核心来处理https://www.cnblogs.com/stubborn412/p/4033651.html
为什么时候用多进程什么时候用多线程:
cpu密集型任务(循环处理,计数,运算等):多进程可以利用多核cpu,多启动一个进程下一个线程工作,可以大大提交cpu的处理速度,而多线程来回切换极大消耗cpu的资源
IO密集型任务(网络爬虫,文件处理等):多线程可以充分利用等待时间,利用其它线程执行代码,而多进程也就是单线程进行IO操作只会傻傻等待
from multiprocessing import Process import time def run():time.sleep(50)print("Zzzzz") if __name__ == '__main__':for i in range(8): # 启动两个进程p = Process(target=run)p.start()
多进程&多线程应用
from multiprocessing import Process,Manager #Manager.dict()可以多进程之间共享数据 import threading import time def run_threading():time.sleep(60)print("Zzzzz---%s" % threading.current_thread()) # 打印线程名称 def xiancheng():for j in range(10): # 启动10个线程p = threading.Thread(target=run_threading)p.start() if __name__ == '__main__':for i in range(10): # 启动10个进程p = Process(target=xiancheng)p.start()
10个为子进程,1一个为主进程,一个为pycharm进程
requests
import requests import nnlog class MyRequest:log_file_name = 'MyRequest.log'#日子文件名time_out = 10 #请求超时时间def __init__(self,url,data=None,headers=None,file=None):self.url = urlself.data = dataself.headers = headersself.file = filedef post(self):try:req = requests.post(self.url,data=self.data,headers=self.headers,files=self.file,timeout=self.time_out)except Exception as e:res = {"status":0,"err_msg":e.args} #0代表请求失败else:try:res = {"status":1,"data":req.json()} #1代表返回的jsonexcept Exception as e:res = {"staus":2,"data":req.text} #2代表返回不是jsonlog_str = 'url: %s 请求方式:post data:%s ,返回数据:%s'%(self.url,self.data,res)self.write_log(log_str)return resdef get(self):try:req = requests.get(self.url,params=self.data,headers=self.headers,timeout=self.time_out)except Exception as e:res = {"status":0,"err_msg":e.args} #0代表请求失败else:try:res = {"status":1,"data":req.json()} #1代表返回的jsonexcept Exception as e:res = {"staus":2,"data":req.text} #2代表返回不是jsonlog_str = 'url: %s get请求 data:%s ,返回数据:%s'%(self.url,self.data,res)self.write_log(log_str)return res@classmethoddef write_log(cls,content):log = nnlog.Logger(cls.log_file_name)log.debug(content)
版权声明:本文原创发表于 博客园,作者为 RainBol 本文欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则视为侵权。