gevent

python并发编程之进程、线程、协程的调度原理(六)

為{幸葍}努か 提交于 2020-04-28 06:41:18
进程、线程和协程的调度和运行原理总结。 系列文章 python并发编程之threading线程(一) python并发编程之multiprocessing进程(二) python并发编程之asyncio协程(三) python并发编程之gevent协程(四) python并发编程之Queue线程、进程、协程通信(五) python并发编程之进程、线程、协程的调度原理(六) python并发编程之multiprocessing进程windows和linux环境的对比(七) 进程、线程的调度策略介绍 linux的操作系统详细调度策略可参考: http://blog.csdn.net/gatieme/article/details/51872659 linux中的进程主要有三种调度策略: 优先级调度:将进程分为普通进程和实时进程; 先进先出(队列)调度:实时进程先创建的先执行,直到遇到io或主动阻塞。 轮转调度(时间片):达到一定的CPU执行时间后强制切换; 多进程程序的调度其实还是线程的调度,线程才是CPU调度的基本单位;在同一个进程内线程切换不会产生进程切换,由一个进程内的线程切换到另一个进程内的线程时,将会引起进程切换。 引起进程or线程调度的原因 正在执行的进程执行完毕; 执行中进程发生阻塞;(如调用sleep) 执行中进程调用了P原语操作,从而因资源不足而被阻塞

Django+celery+redis 异步发送邮件功能

梦想的初衷 提交于 2020-04-28 05:46:23
系统==win10 Django==2.1 redis== 3.2.0 celery==4.2.1 由于目前是在开发过程中,所以测试环境为win10。 开发需求:当用户在页面点击“下载时”,系统会通过用户session获取用户邮箱,使用系统设置的邮箱发送给用户包含指定文件的邮件。 问题1:views.py中,除非系统将邮件已成功发送,才会return页面给用户,由于文件大小和网络环境的问题,发送时间可能较长,不可能让用户长时间等待。 问题2:系统发送邮件的主进程进行时,用户和其他人都无法做新的操作。 解决办法:使用celery将发送邮件的任务转成异步执行,无需用户等待。使用redis作为队列,将异步任务进行缓存。不影响服务器主进程。 开始解决之路: 部署环境 pip3 install redis (这里首先需要下载redis安装,下载链接 https://github.com/MicrosoftArchive/redis/releases ,进入后下载 Redis-x64-3.2.100.zip ),启动命令: 进入解压后的文件 输入:redis-server.exe redis.windows.conf pip3 install celery 目录结构见下图: 将创建两个py文件,tasks.py和celery.py。 tasks.py 内容 from django.conf

python并发编程之multiprocessing进程(二)

杀马特。学长 韩版系。学妹 提交于 2020-04-27 19:05:23
python的multiprocessing模块是用来创建多进程的,下面对multiprocessing总结一下使用记录。 系列文章 python并发编程之threading线程(一) python并发编程之multiprocessing进程(二) python并发编程之asyncio协程(三) python并发编程之gevent协程(四) python并发编程之Queue线程、进程、协程通信(五) python并发编程之进程、线程、协程的调度原理(六) python并发编程之multiprocessing进程windows和linux环境的对比(七) fork() import os pid = os.fork() # 创建一个子进程 if pid == 0: print('这是子进程') print(os.getpid(),os.getppid()) else: print('这是父进程') print(os.getpid()) os.wait() # 等待子进程结束释放资源 fork函数被调用后会返回两次,pid为0的代表子进程,其他返回子进程的id号表示父进程。 getpid和getppid函数可以获取本进程和父进程的id号; fork方式的缺点: 兼容性差,只能在类linux系统下使用,windows系统不可使用; 扩展性差,当需要多条进程的时候,进程管理变得很复杂;

python并发编程之gevent协程(四)

我与影子孤独终老i 提交于 2020-04-27 19:03:27
协程的含义就不再提,在py2和py3的早期版本中,python协程的主流实现方法是使用gevent模块。由于协程对于操作系统是无感知的,所以其切换需要程序员自己去完成。 系列文章 python并发编程之threading线程(一) python并发编程之multiprocessing进程(二) python并发编程之asyncio协程(三) python并发编程之gevent协程(四) python并发编程之Queue线程、进程、协程通信(五) python并发编程之进程、线程、协程的调度原理(六) 基于生成器的简单协程 import time def A(): for i in range(100): print("----A---") yield i time.sleep(0.5) def B(c): while True: print("----B---") try: next(c) except StopIteration: break else: time.sleep(0.5) if __name__ == '__main__': a = A() B(a) 上面的例子并没有带来代码效率的提高,因为time.sleep()是同步阻塞操作;上例主要是为了说明协程的上下文切换原理。 greenlet的协程 greenlet模块也是程序显性主动控制协程切换

python中socket、socketio、flask-socketio、WebSocket的区别与联系

别说谁变了你拦得住时间么 提交于 2020-04-26 02:50:13
socket、socketio、flask-socketio、WebSocket的区别与联系 socket 是通信的基础,并不是一个协议,Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族和UDP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。 WebSocket 是html5新增加的一种通信协议,可以类比于http协议。常见的应用方式如弹幕、web在线游戏。 socketio 是基于socket连接后(并没有自己实现socket的链接而是复用了web框架或gevent、eventlet中的socket)对网络输入输出流的处理,封装了send、emit、namespace、asyncio 、订阅等接口,同时扩展使用了redis、rabbitmq消息队列的方式与其他进程通信。 flask-socketio 是socketio对flask的适配,封装了emit、send和关于room的操作。 select的链接、发送等底层操作还是在flask中做的,socketio对其做了抽象。使用threading模式时并没有自己实现socket的链接而是复用了web框架的socket

python并发编程之threading线程(一)

筅森魡賤 提交于 2020-04-22 04:20:53
进程是系统进行资源分配最小单元,线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.进程在执行过程中拥有独立的内存单元,而多个线程共享内存等资源。 系列文章 python并发编程之threading线程(一) python并发编程之multiprocessing进程(二) python并发编程之asyncio协程(三) python并发编程之gevent协程(四) python并发编程之Queue线程、进程、协程通信(五) python并发编程之进程、线程、协程的调度原理(六) threading模块创建线程 import threading from threading import Thread def test(x): print('this is {}'.format(x)) time.sleep(2) def get_thread(number=5): l_thread = (Thread(target=test, args=(i,)) for i in range(number)) for t in l_thread: print(t) t.start() # 启动线程开始执行 print(len(threading.enumerate())) if __name__ == '__main__': get_thread(5) #

Python memory profiler 上手实践

岁酱吖の 提交于 2020-04-12 07:31:16
为什么 相比起 C ,Python 有自己的内存管理,不需开发者自己管理内存。虽然方便,但有时候,我们可能会遇到内存占用过高,内存泄漏,甚至 OOM 的情况。这时,就需要我们做内存诊断,了解自己的代码:内存主要被分配在哪里,是否有无法释放的内存,又有多少内存会很快被释放,进程在高峰时占用多少内存,在低谷时占用多少内存。 怎么办 要了解进程的内存使用情况,我们可能首先会想到使用 TOP 命令,查看进程内存的使用情况。TOP 命令能够实时查看到进程对各种资源的使用情况,也是我们经常会使用的Linux命令。而在 Python 中,通过 psutil 模块也能很好的获取到这些信息。 这两个工具十分的强大,但是也很基础。TOP命令不方便从更多的维度诊断问题,比如难以从时间维度诊断内存,只能统计当前整个进程的内存使用情况,与代码脱离。而 psutil 十分强大,可以和代码结合,但是对逻辑代码侵入性太强,比如想在某个函数前后统计内存的使用情况,就需要在原有代码的基础上插桩,产生不必要的耦合,而不侵入逻辑代码则又和使用命令行没有太大区别。 这个时候,有经验的朋友可能会想到 line_profiler。line_profiler 是用于对函数进行逐行分析的模块,只需要通过装饰器,就可以计算出函数内每一行代码的执行时间,以提供时间维度的性能诊断。那么在内存维度上,是不是也有类似的模块呢?bingo

Python爬虫案例演示:Python多线程、多进程、协程

安稳与你 提交于 2020-04-07 15:32:41
很多时候我们写了一个爬虫,实现了需求后会发现了很多值得改进的地方,其中很重要的一点就是爬取速度。本文 就通过代码讲解如何使用 多进程、多线程、协程 来提升爬取速度。注意:我们不深入介绍理论和原理,一切都在代码中。 二、同步 首先我们写一个简化的爬虫,对各个功能细分,有意识进行函数式编程。下面代码的目的是访问300次百度页面并返回状态码,其中 parse_1 函数可以设定循环次数,每次循环将当前循环数(从0开始)和url传入 parse_2 函数。 import requestsdef parse_1(): url = 'https://www.baidu.com' for i in range(300): parse_2(url)def parse_2(url): response = requests.get(url) print(response.status_code)if __name__ == '__main__': parse_1() 性能的消耗主要在IO请求中,当单进程单线程模式下请求URL时必然会引起等待 示例代码就是典型的串行逻辑, parse_1 将url和循环数传递给 parse_2 , parse_2 请求并返回状态码后 parse_1 继续迭代一次,重复之前步骤 三、多线程 因为CPU在执行程序时每个时间刻度上只会存在一个线程

gfirefly 框架分析

喜欢而已 提交于 2020-04-07 03:49:44
数据包 协议 协议如下表 | HEAD_0 | ... | HEAD_3 | protoVersion | serverVersion | length | |--------|--------|--------|--------|--------|--------| | char | ... | char | int | int | int | gfirefly 框架是基于TCP协议的长连接,框架中 没有使用keep-alive ,那么网络异常断开(如网线突然拔掉)的时候,应用层是不知道,当我们自己使用的时候就必须加心跳包等机制来解决这个问题。另外数据加密没有放到协议层,那么需要加密数据只能在打包数据之前使用加密算法。 黏包 gfirefly中对底层的数据包进行了黏包处理,如上表所示,协议头定义了length,此时应用层就知道什么时候结束单个包的传输。见gfirefly/netconnect/protoc.py line 43: def dataReceived(self, data): length = self.factory.dataprotocl.getHeadlength()#获取协议头的长度 self.buff += data while self.buff.__len__() >= length: unpackdata = self.factory

python的多线程、多进程、协程用代码详解

醉酒当歌 提交于 2020-04-06 16:39:40
前言 文的文字及图片来源于网络,仅供学习、交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理。 作者:刘早起早起 PS:如有需要Python学习资料的小伙伴可以加点击下方链接自行获取http://t.cn/A6Zvjdun 很多时候我们写了一个爬虫,实现了需求后会发现了很多值得改进的地方,其中很重要的一点就是爬取速度。本文就通过代码讲解如何使用 多进程、多线程、协程 来提升爬取速度。注意:我们不深入介绍理论和原理,一切都在代码中。 同步 首先我们写一个简化的爬虫,对各个功能细分,有意识进行函数式编程。下面代码的目的是访问300次百度页面并返回状态码,其中parse_1函数可以设定循环次数,每次循环将当前循环数(从0开始)和url传入parse_2函数。 性能的消耗主要在IO请求中,当单进程单线程模式下请求URL时必然会引起等待 示例代码就是典型的串行逻辑,parse_1将url和循环数传递给parse_2,parse_2请求并返回状态码后parse_1继续迭代一次,重复之前步骤 多线程 因为CPU在执行程序时每个时间刻度上只会存在一个线程,因此多线程实际上提高了进程的使用率从而提高了CPU的使用率 实现多线程的库有很多,这里用concurrent.futures中的ThreadPoolExecutor来演示