网站性能检测评分
注:本网站页面html检测工具扫描网站中存在的基本问题,仅供参考。
python最多能开几个进程
python3应用准备知识三:进程和线程一 推广视频课程
现在的计算机的操作系统不管是windows还是linux或者mac都属于多任务操作系统,比如你可以一般听歌一边玩游戏,或者你打开网站然后聊QQ都是多任务的表现。
进程一般指的是一个程序的执行
线程是指进程内的一个执行单元,也是进程内的可调度实体.
与进程的区别:
(1)地址空间:进程内的一个执行单元;进程至少有一个线程;它们共享进程的地址空间;而进程有自己独立的地址空间;
(2)资源拥有:进程是资源分配和拥有的单位,同一个进程内的线程共享进程的资源
(3)线程是处理器调度的基本单位,但进程不是.
4)二者均可并发执行.
进程和线程都是由操作系统所体会的程序运行的基本单元,系统利用该基本单元实现系统对应用的并发性。进程和线程的区别在于:
简而言之,一个程序至少有一个进程,一个进程至少有一个线程.
线程的划分尺度小于进程,使得多线程程序的并发性高。
另外,进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率。
线程在执行过程中与进程还是有区别的。每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。
从逻辑角度来看,多线程的意义在于一个应用程序中,有多个执行部分可以同时执行。但操作系统并没有将多个线程看做多个独立的应用,来实现进程的调度和管理以及资源分配。这就是进程和线程的重要区别。
进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位.
线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源.
一个线程可以创建和撤销另一个线程;同一个进程中的多个线程之间可以并发执行.
python3提供了很好的进线程管理函数,我们今天就来学习一下进线程在python3里面的应用:
多进程操作:
这里我们要引入os模块
Unix/Linux操作系统提供了一个fork()系统调用,它非常特殊。一般函数调用一次,返回一次,但是fork()调用一次,返回两次,因为操作系统自动把当前进程(称为父进程)复制了一份(称为子进程),然后,分别在父进程和子进程内返回。
子进程永远返回0,而父进程返回子进程的ID。这样做的理由是,一个父进程可以fork出很多子进程,所以,父进程要记下每个子进程的ID,而子进程只需要调用getpid()就可以拿到父进程的ID。
import os #先导入os模块
print('Process (%s) start...' % os.getpid()) #程序一开始就会生成一个主进程
pid = os.fork() #再调用依次fork()函数产生一个子进程
if pid == 0: #如果调用成功则有返回值
print('I am child process (%s) and my parent is %s.' % (os.getpid(), os.getppid())) #通过getpid()
else:
print('I (%s) just created a child process (%s).' % (os.getpid(), pid)) #pid是返回的子进程
以上代码是只能在linux和Unix和mac操作系统上
windows上是不能用fork()来做进程操作,放心Python是跨平台的,自然也应该提供一个跨平台的多进程支持。multiprocessing模块就是跨平台版本的多进程模块。
multiprocessing模块提供了一个Process类来代表一个进程对象。
from multiprocessing import Process #导入Process函数
import os
def run_proc(name): #Process函数的第一个参数需要需要一个执行函数
print('Run child process %s (%s)...' % (name, os.getpid())) #os.getpid()依然可以取进程id
if __name__=='__main__': #程序启动确保不是调用启动
print('Parent process %s.' % os.getpid()) #先用os.getpid()调用主进程
p = Process(target=run_proc, args=('test',)) #Process函数调用,给子进程命名test返回一个实例p
print('Child process will start.')
p.start() # p.start() 开始一个子进程
p.join() # p.join() 关闭一个子进程
print('Child process end.')
在windows里面记得关闭进程,负责会一直占用内存
下一节我们再仔细说一下进程进程池线程和管道等。今天的你们学会了吗,有什么问题记得给我留言哦
刚开始学习的小白学Python,他对线程和进程的理解让我非常惊讶! 企业视频课程
目录
线程与进程
线程与进程是操作系统里面的术语,简单来讲,每一个应用程序都有一个自己的进程。在给大家分享之前呢,小编推荐一下一个挺不错的交流宝地,里面都是一群热爱并在学习Python的小伙伴们,大几千了吧,各种各样的人群都有,特别喜欢看到这种大家一起交流解决难题的氛围,群资料也上传了好多,各种大牛解决小白的问题,这个Python群:330637182 欢迎大家进来一起交流讨论,一起进步,尽早掌握这门Python语言。
操作系统会为这些进程分配一些执行资源,例如内存空间等。在进程中,又可以创建一些线程,他们共享这些内存空间,并由操作系统调用,以便并行计算。
我们都知道现代操作系统比如 Mac OS X,UNIX,Linux,Windows 等可以同时运行多个任务。打个比方,你一边在用浏览器上网,一边在听敲代码,一边用 Markdown 写博客,这就是多任务,至少同时有 3 个任务正在运行。当然还有很多任务悄悄地在后台同时运行着,只是桌面上没有显示而已。对于操作系统来说,一个任务就是一个进程(Process),比如打开一个浏览器就是启动一个浏览器进程,打开 PyCharm 就是一个启动了一个 PtCharm 进程,打开 Markdown 就是启动了一个 Md 的进程。
虽然现在多核 CPU 已经非常普及了。可是由于 CPU 执行代码都是顺序执行的,这时候我们就会有疑问,单核 CPU 是怎么执行多任务的呢?
其实就是操作系统轮流让各个任务交替执行,任务 1 执行 0.01 秒,切换到任务 2 ,任务 2 执行 0.01 秒,再切换到任务 3 ,执行 0.01秒……这样反复执行下去。表面上看,每个任务都是交替执行的,但是,由于 CPU的执行速度实在是太快了,我们肉眼和感觉上没法识别出来,就像所有任务都在同时执行一样。
真正的并行执行多任务只能在多核 CPU 上实现,但是,由于任务数量远远多于 CPU 的核心数量,所以,操作系统也会自动把很多任务轮流调度到每个核心上执行。
有些进程不仅仅只是干一件事的啊,比如浏览器,我们可以播放时视频,播放音频,看文章,编辑文章等等,其实这些都是在浏览器进程中的子任务。在一个进程内部,要同时干多件事,就需要同时运行多个“子任务”,我们把进程内的这些“子任务”称为线程(Thread)。
由于每个进程至少要干一件事,所以,一个进程至少有一个线程。当然,一个进程也可以有多个线程,多个线程可以同时执行,多线程的执行方式和多进程是一样的,也是由操作系统在多个线程之间快速切换,让每个线程都短暂地交替运行,看起来就像同时执行一样。
那么在 Python 中我们要同时执行多个任务怎么办?
有两种解决方案:
一种是启动多个进程,每个进程虽然只有一个线程,但多个进程可以一块执行多个任务。
还有一种方法是启动一个进程,在一个进程内启动多个线程,这样,多个线程也可以一块执行多个任务。
当然还有第三种方法,就是启动多个进程,每个进程再启动多个线程,这样同时执行的任务就更多了,当然这种模型更复杂,实际很少采用。
总结一下就是,多任务的实现有3种方式:
多进程模式;
多线程模式;
多进程+多线程模式。
同时执行多个任务通常各个任务之间并不是没有关联的,而是需要相互通信和协调,有时,任务 1 必须暂停等待任务 2 完成后才能继续执行,有时,任务 3 和任务 4 又不能同时执行,所以,多进程和多线程的程序的复杂度要远远高于我们前面写的单进程单线程的程序。
因为复杂度高,调试困难,所以,不是迫不得已,我们也不想编写多任务。但是,有很多时候,没有多任务还真不行。想想在电脑上看电影,就必须由一个线程播放视频,另一个线程播放音频,否则,单线程实现的话就只能先把视频播放完再播放音频,或者先把音频播放完再播放视频,这显然是不行的。
多线程编程
其实创建线程之后,线程并不是始终保持一个状态的,其状态大概如下:
New 创建
Runnable 就绪。等待调度
Running 运行
Blocked 阻塞。阻塞可能在 Wait Locked Sleeping
Dead 消亡
线程有着不同的状态,也有不同的类型。大致可分为:
主线程
子线程
守护线程(后台线程)
前台线程
简单了解完这些之后,我们开始看看具体的代码使用了。
1、线程的创建
Python 提供两个模块进行多线程的操作,分别是 thread和 threading
前者是比较低级的模块,用于更底层的操作,一般应用级别的开发不常用。
运行结果:
注意喔,这里不同的环境输出的结果肯定是不一样的。
2、线程合并(join方法)
上面的示例打印出来的结果来看,主线程结束后,子线程还在运行。那么我们需要主线程要等待子线程运行完后,再退出,要怎么办呢?
这时候,就需要用到 join方法了。
在上面的例子,新增一段代码,具体如下:
从打印的结果,可以清楚看到,相比上面示例打印出来的结果,主线程是在等待子线程运行结束后才结束的。
3、线程同步与互斥锁
使用线程加载获取数据,通常都会造成数据不同步的情况。当然,这时候我们可以给资源进行加锁,也就是访问资源的线程需要获得锁才能访问。
4、Condition 条件变量
实用锁可以达到线程同步,但是在更复杂的环境,需要针对锁进行一些条件判断。Python 提供了 Condition 对象。使用 Condition 对象可以在某些事件触发或者达到特定的条件后才处理数据,Condition 除了具有 Lock 对象的 acquire 方法和 release 方法外,还提供了 wait 和 notify 方法。线程首先 acquire 一个条件变量锁。如果条件不足,则该线程 wait,如果满足就执行线程,甚至可以 notify 其他线程。其他处于 wait 状态的线程接到通知后会重新判断条件。
其中条件变量可以看成不同的线程先后 acquire 获得锁,如果不满足条件,可以理解为被扔到一个( Lock 或 RLock )的 waiting 池。直达其他线程 notify 之后再重新判断条件。不断的重复这一过程,从而解决复杂的同步问题。
Condition
该模式常用于生产者消费者模式,具体看看下面在线购物买家和卖家的示例:
输出的结果如下:
5、线程间通信
如果程序中有多个线程,这些线程避免不了需要相互通信的。那么我们怎样在这些线程之间安全地交换信息或数据呢?
从一个线程向另一个线程发送数据最安全的方式可能就是使用 queue 库中的队列了。创建一个被多个线程共享的 Queue对象,这些线程通过使用 put()和 get() 操作来向队列中添加或者删除元素。
Python 还提供了 Event 对象用于线程间通信,它是由线程设置的信号标志,如果信号标志位真,则其他线程等待直到信号接触。
Event 对象实现了简单的线程通信机制,它提供了设置信号,清楚信号,等待等用于实现线程间的通信。
设置信号
6、后台线程
默认情况下,主线程退出之后,即使子线程没有 join。那么主线程结束后,子线程也依然会继续执行。如果希望主线程退出后,其子线程也退出而不再执行,则需要设置子线程为后台线程。Python 提供了 setDeamon方法。
进程
Python 中的多线程其实并不是真正的多线程,如果想要充分地使用多核 CPU 的资源,在 Python 中大部分情况需要使用多进程。Python 提供了非常好用的多进程包 multiprocessing,只需要定义一个函数,Python 会完成其他所有事情。借助这个包,可以轻松完成从单进程到并发执行的转换。multiprocessing 支持子进程、通信和共享数据、执行不同形式的同步,提供了 Process、Queue、Pipe、Lock 等组件。
下面看一个创建函数并将其作为多个进程的例子:
输出的结果:
多进程输出结果
2、把进程创建成类
当然我们也可以把进程创建成一个类,如下面的例子,当进程 p 调用 start() 时,自动调用 run() 方法。
输出结果如下:
创建进程类
3、daemon 属性
想知道 daemon 属性有什么用,看下下面两个例子吧,一个加了 daemon 属性,一个没有加,对比输出的结果:
没有加 deamon 属性的例子:
在上面示例中,进程 p 添加 daemon 属性:
根据输出结果可见,如果在子进程中添加了 daemon 属性,那么当主进程结束的时候,子进程也会跟着结束。所以没有打印子进程的信息。
4、join 方法
结合上面的例子继续,如果我们想要让子线程执行完该怎么做呢?
那么我们可以用到 join 方法,join 方法的主要作用是:阻塞当前进程,直到调用 join 方法的那个进程执行完,再继续执行当前进程。
因此看下加了 join 方法的例子:
5、Pool
如果需要很多的子进程,难道我们需要一个一个的去创建吗?
当然不用,我们可以使用进程池的方法批量创建子进程。
例子如下:
6、进程间通信
Process 之间肯定是需要通信的,操作系统提供了很多机制来实现进程间的通信。Python 的 multiprocessing 模块包装了底层的机制,提供了Queue、Pipes 等多种方式来交换数据。
以 Queue 为例,在父进程中创建两个子进程,一个往 Queue 里写数据,一个从 Queue 里读数据:
谢谢阅读,此篇为草根学Python。非常全面!
python多进程快速批量爬取黄页海量信息并保存文本和数据库教程 推广视频课程
最近帮朋友做一些网络营销的工作,需要抓取一些客源信息,用以辅助营销,我感觉很多做电商的朋友,尤其是微商朋友们,应该都是比较需要各种客源信息的吧,今天,小编我就借此机会把利用python多进程的方式抓取黄页海量的客源信息的方法分享给大家,希望大家能多多关注本人,多讨论关于爬虫和数据挖掘分析相关的问题。
该代码已经上传至本人的github,喜欢的朋友可到我的公众号获取。
一、特别提到的库:
多进程:pool
mogo数据库:pymongo
自然语言编码转换:codecs
二、特别推荐----jupyter
做开发没有趁手的兵器是不行的,对于python脚本的开发以及做一些数据挖掘和分析这方面工作来说,jupyter notebook这个工具是一个非常合适的工具,它可以保存你写的阶段性的小脚本,同时,又不至于像ipython那样把有价值的历史代码被滚屏所淹没,关于这个工具的其他优点,大家可以自行百度,总之,这是一个python开发的一个神器,借助它可以快速的写出很多高效的代码出来。
三、主要代码:
这次抓取的站点是黄页88网,网站放置行业信息的结构是这样的,按照行业来抓取的话,首先是分为各种行业,每种行业下面又可以获取到各个省份的该行业的信息。
为了能够按照行业进行抓取,我们可以先把首页出现的行业分类抓取下来,保存为字典,这一步的方法就不仔细说了,请自行解决。我已经保存好了字典,将起保存在一个单独的配置文件中,方便调用时使用。
获取各个行业对应的每个省的url,我们可以写一个函数来完成,返回一个url的列表。
有了这个url以后,就可以直接得到内容了,其中翻页的时候需要注意url中控制页码是通过pn变量实现的,也需要对最后一页做一下判断,否则就会形成死循环。这一步就已经把数据写入了txt文件中。
最后是执行爬虫的的代码,这里用到了多线程,同时需要存入mongodb的数据库。
由于自媒体发布的时候贴代码不太方便,感兴趣的朋友关注我的同名订阅号获取github地址吧!