python学习之多线程多进程
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):#方法必须叫run
time.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("")
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 num
lock.acquire() # 加锁
num += 1
lock.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 = url
self.data = data
self.headers = headers
self.file = file
def 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代表返回的json
except Exception as e:
res = {"staus":2,"data":req.text} #2代表返回不是json
log_str = 'url: %s 请求方式:post data:%s ,返回数据:%s'%(self.url,self.data,res)
self.write_log(log_str)
return res def 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代表返回的json except Exception as e:
res = {"staus":2,"data":req.text} #2代表返回不是json
log_str = 'url: %s get请求 data:%s ,返回数据:%s'%(self.url,self.data,res)
self.write_log(log_str)
return res @classmethod
def write_log(cls,content):
log = nnlog.Logger(cls.log_file_name)
log.debug(content)
#ThreadPoolExecutor线程池的submit
import time
import requests
from concurrent.futures import ThreadPoolExecutor, wait def time_ji(fuc):
def wrapping(*args, **kwargs):
start = time.time()
fuc(*args, **kwargs)
res = time.time() - start
print(res)
return return wrapping
hread = ThreadPoolExecutor(max_workers=2)
page = [x for x in range(1, 6)]
urls01 = ['http://rainbol.cn?page=%s' % i for i in page]
urls01.append('http://www.baidu.com')
list01 = []
@time_ji
def run(i):
res = requests.get(i)
print(i, str(len(res.text)) + '字节')
for i in urls01:
result_submit = thread.submit(run,i)
list01.append(result_submit)
wait(list01) # 等待其他线程工作完成后再执行下面操作
print('都执行完了')
#submit:
# http://rainbol.cn?page=1 35489字节
# 0.07800006866455078
# http://rainbol.cn?page=2 35712字节
# 0.12480020523071289
# http://rainbol.cn?page=3 35534字节
# 0.07800030708312988
# http://rainbol.cn?page=4 35495字节
# 0.06240034103393555
# http://www.baidu.com 2381字节
# 0.14039993286132812
# http://rainbol.cn?page=5 25010字节
# 0.32760047912597656 #ThreadPoolExecutor线程池的submit
import time
def time_ji(fuc):
def wrapping(*args, **kwargs):
start = time.time()
fuc(*args, **kwargs)
res = time.time() - start
print(res)
return
return wrapping
import requests
from concurrent.futures import ThreadPoolExecutor, wait
thread = ThreadPoolExecutor(max_workers=2)
page = [x for x in range(1, 6)]
urls01 = ['http://rainbol.cn?page=%s' % i for i in page]
urls01.append('http://www.baidu.com')
list01 = []
@time_ji
def run(i):
res = requests.get(i)
print(i, str(len(res.text)) + '字节')
result_map = list(thread.map(run, urls01))
print('都执行完了')
#http://rainbol.cn?page=2 35712字节
#0.09200549125671387
#http://rainbol.cn?page=1 35489字节
#0.12100696563720703
#http://rainbol.cn?page=3 35534字节
#0.08300471305847168
#http://rainbol.cn?page=4 35495字节
#0.10100579261779785
#http://www.baidu.com 2381字节
#0.06100344657897949
#http://rainbol.cn?page=5 25010字节
#0.28101587295532227
#都执行完了 #ProcessPoolExecutor进程
from concurrent.futures import ProcessPoolExecutor, wait
import time
import requests
page = [x for x in range(1, 6)]
urls01 = ['http://rainbol.cn?page=%s' % i for i in page]
urls01.append('http://www.baidu.com')
def run(i):
start = time.time()
res = requests.get(i)
print(i, str(len(res.text)) + '字节')
print(time.time()-start )
process1 = ProcessPoolExecutor(max_workers=2)
if __name__ == '__main__': #必须加main不然会报错
list01 = []
for i in urls01:
result_map = process1.submit(run, i)
list01.append(result_map)
wait(list01)
print('都执行完了')
http://rainbol.cn?page=1 35489字节
0.08200478553771973
http://rainbol.cn?page=2 35712字节
0.10700583457946777
http://rainbol.cn?page=3 35534字节
0.09300518035888672
http://rainbol.cn?page=4 35495字节
0.08600473403930664
http://rainbol.cn?page=5 25010字节
0.06000328063964844
http://www.baidu.com 2381字节
0.06800413131713867
都执行完了
版权声明:本文原创发表于 博客园,作者为 RainBol本文欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则视为侵权。
python学习之多线程多进程的更多相关文章
- python学习笔记之四-多进程&多线程&异步非阻塞
		ProcessPoolExecutor对multiprocessing进行了高级抽象,暴露出简单的统一接口. 异步非阻塞 爬虫 对于异步IO请求的本质则是[非阻塞Socket]+[IO多路复用]: & ... 
- python学习笔记- 多线程(1)
		学习多线程首先先要理解线程和进程的关系. 进程 计算机的程序是储存在磁盘中的可执行的二进制文件,执行时把这些二进制文件加载到内存中,操作系统调用并交给处理器执行对应操作,进程是程序的一次执行过程,这是 ... 
- python学习笔记——multiprocessing 多进程组件-队列Queue
		1 消息队列 1.1 基本语法 消息队列:multiprocessing.Queue,Queue是对进程安全的队列,可以使用Queue实现对进程之间的数据传输:还有一个重要作用是作为缓存使用. Que ... 
- 2019-02-02 Python学习之多线程
		1.主线程和次线程 若主线程结束则次线程也会结束 如何避免主线程先结束: 结尾处加上 while True: pass e.g. import win32api #引用系统函数 import _thr ... 
- python学习笔记——multiprocessing 多进程组件 Pipe管道
		进程间通信(IPC InterProcess Communication)是值在不同进程间传播或交换信息. IPC通过有管道(无名管道 和 有名 / 命名管道).消息队列.共享存储 / 内容.信号量. ... 
- python学习笔记——multiprocessing 多进程组件 进程池Pool
		1 进程池Pool基本概述 在使用Python进行系统管理时,特别是同时操作多个文件目录或者远程控制多台主机,并行操作可以节约大量时间,如果操作的对象数目不大时,还可以直接适用Process类动态生成 ... 
- python学习笔记——multiprocessing 多进程模块Process
		系统自带的fork模块创建的多进程是基于Linux或Unix平台的,而window平台并不支持: python中的multiprocess为跨平台版本的多进程模块,支持子进程.通信和共享数据.执行不同 ... 
- Python学习 :多线程 --- 锁
		多线程 什么是锁? - 锁通常被用来实现对共享资源的同步访问. - 为每一个共享资源创建一个Lock对象,当你需要访问该资源时,调用acquire方法来获取锁对象(如果其它线程已经获得了该锁,则当前线 ... 
- Python学习 :多线程
		多线程 什么是线程? - 能独立运行的基本单位——线程(Threads). - 线程是操作系统能够进行运算调度的最小单位.它被包含在进程之中,是进程中的实际运作单位. - 一条线程指的是进程中一个单一 ... 
随机推荐
- [一点感触]ADF4350 ADF4111混频记
			几经周折,还是和jack顺利的调完了二者的混频,回想起来我发的上一个版本是2016-11-29,时间可能永远停留在这里了... 祝您一路走好,未来的世界不再忙碌.奔波! 发两张界面纪念吧: 也曾想着把 ... 
- R去掉含有NA的行
			只要数据框中含有NA的行都去掉 final[complete.cases(final),] na.omit(final) 过滤某几列 final[complete.cases(final[,5:6]) ... 
- 在Ubuntu下安装qt
			安装qt前的准备: 安装基础开发包,主要gcc,g++等: sudo apt-get install build-essential 1. 使用qt-opensource-linux-x86-5.5. ... 
- Bayesian machine learning
			from: http://www.metacademy.org/roadmaps/rgrosse/bayesian_machine_learning Created by: Roger Grosse( ... 
- [.Net] - 使用 iTextSharp 生成基于模板的 PDF,生成新文件并保留表单域
			背景 基于 PDF Template 预填充表单项,生成一份新的 PDF 文件,并保留表单域允许继续修改. 代码段 using iTextSharp.text.pdf; /* Code Snippet ... 
- Linux7 安装python3.5.4
			1.首先修改yum配置文件 因为yum使用python2,因此替换为python3后可能无法正常工作,继续使用这个python2.7.5 因此修改yum配置文件(vi /usr/bin/yum). 把 ... 
- Python14之字符串(各种奇葩的内置方法)
			一.字符串的分片操作 其分片操作和列表和元组一样 str1 = 'keshengtao' str1[2:6] 'shen' str1[:] 'keshengtao' str1[:4] 'kesh' 二 ... 
- Java字符串定义及常用方法
			String.StringBuffer和StringBuilder String修饰的是不可变的字符串,而StringBuffer和StringBuilder类的对象是可以被修改的. Stri ... 
- 第三章 hash是个啥玩意
			3.10 hash 什么是哈希? hash,一般翻译做散列.杂凑,或音译为哈希,是把任意长度的输入(又叫做预映射pre-image)通过散列算法变换成固定长度的输出,该输出就是散列值.这种转换是一种压 ... 
- 小贴士--java篇
			1. java: “.”和“|”都是转义字符,必须得加"\\" 2.java :如果在一个字符串中有多个分隔符,可以用“|”作为连字符,比如:“acount=? and uu = ... 
