Python基础之进程详解

一、前言

进程,一个新鲜的字眼,可能有些人并不了解,它是系统某个运行程序的载体,这个程序可以有单个或者多个进程,一般来说,进程是通过系统CPU 内核数来分配并设置的,我们可以来看下系统中的进程:

可以看到,360浏览器是真的皮,这么多进程啊,当然可以这样来十分清楚的看进程线程使用情况:

通过任务管理器中的资源监视器,是不是很厉害了,哈哈哈。讲完了这些,再说说用法。

二、基本用法

进程能干什么,这是我们要深思熟虑的事情。我们都知道一个程序运行会创建进程,所以程序在创建这些进程的时候,为了让它们更能有条不紊的工作,肯定也加入了线程。

那么一条进程里面就会有多个线程协同作战,但是进程不可以创建过多,不然会消耗资源,除非你开发的是一个大型的系统。那么,我们现在就来创建一个进程吧。

一、创建进程 1.在创建进程之前,我们先导入进程的模块,代码如下:

import multiprocess as m
m.Process(target,args)

其实这种写法是不对的,就好比bs4中的BeautifulSoup,你想通过先导入bs4,然后再引入BeautifulSoup是行不通的,必须这样:

from multiprocessing import Process
Process(group, target, args, kwargs, name)
group:用户组
target:调用函数
args:参数元祖
kwargs:参数字典
name:子进程名称

可以看出进程和线程的用法基本差不多,只是名称功能不同而已。而且还有很多其它优秀的方法:

# 返回当前进程存活的子进程的列表。调用该方法有“等待”已经结束的进程的副作用。
multiprocessing.active_children()

# 返回系统的CPU数量。
multiprocessing.cpu_count()

三、创建单个进程

由上述参数可知函数的返回值,基本与线程无差异化。

#启动进程,调用进程中的run()方法。
start()

#进程活动的方法
run()

#强制终止进程,不会进行任何清理操作。如果终止前创建了子进程,那么该子进程在其强制结束后变为僵尸进程;如果该进程还保存了一个锁,那么也将不会被释放,进而导致死锁。
terminate()

#判断某进程是否存活,存活返回True,否则False。
is_alive()

主线程等待子线程终止。timeout为可选择超时时间;需要强调的是:p.join只能join住start开启的进程,而不能join住run开启的进程。
join([timeout])

#设置进程为后台守护进程;当该进程的父进程终止时,该进程也随之终止,并且该进程不能创建子进程,设置该属性必须在start()之前
daemon

#进程名称。
name

#进程pid,在start后才能产生
pid

#子进程的退出代码。如果进程尚未终止,这将是 None,负值-N表示子进程被信号N终止。
exitcode

#进程身份验证,默认是os.urandom()随机生成的字符串。校验网进程连接是否正确
authkey

#系统对象的数字句柄,当进程结束时将变为 "ready" 。
sentinel

#杀进程
kill()

#关闭进程
close()

请注意:创建进程务必将它加入如下语句中:

if __name__ == '__main__':

这样就实现了我们的一个关于进程的程序了。另外我们也可以通过继承进程类来实现:

可以说我们每创建一个进程它就会有一个ID来标志它,下面情况:

四、创建多个进程

单个进程往往都是不够用的,所有我们需要创建一个多进程,多进程创建方法也很简单,加一层循环即可:

这样就轻松创建了多进程的任务,速度比以往就要更快了。

五、进程池

进程池的设计之初就是为了方便我们更有效的利用资源,避免浪费,如果任务量大就多个核一起帮忙,如果少就只开一两个核,下面我们来看看实现过程:

首先导入包:

from multiprocessing import Pool
import multiprocessing as m

进程池的安装包为Pool,然后我们来看下它的CPU内核数:

num=m.cpu_count()#CPU内核数

紧接着我们在来创建进程池:

pool=multiprocessing.Pool(num)

进程池中也有很多方法供我们使用:

apply(func,args,kwargs)                 同步执行(串行) 阻塞

apply_async(func,args,kwargs)           异步执行(并行) 非阻塞

terminate()            强制终止进程,不在处理未完成的任务。

join()     主进程阻塞,等待子进程的退出。必须在close或terminate()之后使用

close()            等待所有进程结束后,才关闭进程池

map(func,iterable,chunksize=int) map函数的并行版本,保持阻塞直到获得结果

#返回一个可用于获取结果的对象,回调函数应该立即执行完成,否则会阻塞负责处理结果的线程
map_async(func,iterable,chunksize,callback,error_callback)

imap(func,iterable,chunksize) map的延迟执行版本

#和imap() 相同,只不过通过迭代器返回的结果是任意的
imap_unordered(func,iterable,chunksize)

#和 map() 类似,不过 iterable 中的每一项会被解包再作为函数参数。
starmap(func,iterable,chunksize)

为此我们可以创建同步和异步的程序,如果你对这对于爬虫来说是很不错的选择,小点的爬虫同步就好,大的爬虫异步效果更佳,很多人不了解异步和同步,其实同步异步就是串行和并行的意思串行和并行简单点说就是串联和并联。下面我们通过实例一起来看一下:

串行

并行

可以看到,仅仅只是一个参数的变化而已,其它的都是大同小异,我们获取到了当前进程的pid,然后把它打印出来了。

六、锁

虽然异步编程多进程给我们带来了便利,但是进程启动后是不可控的,我们需要将它控制住,让它干我们觉得有意义的事,这个时候我们需要给它加锁,和线程一样都是lock:

首先导入进程锁的模块:

from multiprocessing import Lock

然后我们来创建一个关于锁的程序:

可以看到,加锁的过程还是比较顺利的,跟多线程一样简单,但是相对来说速度会慢一点。既然有Lock,那么势必就有RLock了,在python 中,进程和线程的很多用法一致,锁就是。我们可以把它改为RLock,下面便是可重入锁,也就是可以递归:

import time
lock1=RLock()
lock2=RLock()
s=time.time()
def jc(num):
    lock1.acquire()
    lock2.acquire()
    print('start')
    print(m.current_process().pid,'run----',str(num))
    lock1.release()
    lock2.release()
    print('end')
if __name__ == '__main__':
    aa=[]
    for y in range(12):
        pp=Process(target=jc,args=(y,))
        pp.start()
        aa.append(pp)
    for x in aa:
        x.join()
    e=time.time()
    print(e-s)

七、进程间通信

Event

进程间用于通信,方法和线程的一模一样,这里举个小栗子,不在详细描述,不懂的可以看我上一篇关于线程的文章,我们今天要讲的是其它的进程间通信方式,下面请看:

import time
e=Event()
def main(num):
    while True:
        if num<5:
            e.clear()   #清空信号标志
            print('清空')
        if num>=5:
            e.wait(timeout=1) #等待信号标志为真
            e.set()
            print('启动')

        if num==10:
            e.wait(timeout=3)
            e.clear()
            print('退出')
            break
        num+=1
        time.sleep(2)
if __name__ == '__main__':
    for y in range(10):
        pp=Process(target=main,args=(y,))
        pp.start()
        pp.join()

管道传递消息

管道模块初始化后返回两个参数,一个为发送者,一个为接收者,它有个参数可以设置模式为全双工或者半双工,全双工收发一体,半双工只收或者只发,先了解下它的方法:

p1,p2=m.Pipe(duplex=bool) #设置是否全双工,返回两个连接对象
p1.send()  #发送
p2.recv()  #接收
p1.close()  #关闭连接
p1.fileno() #返回连接使用的整数文件描述符
p1.poll([timeout]) #如果连接上的数据可用,返回True,timeout指定等待的最长时限。
p2.recv_bytes([maxlength]) #接收最大字节数
p1.send_bytes([maxlength]) #发送最大字节数
#接收一条完整的字节消息,并把它保存在buffer对象中,offset指定缓冲区中放置消息处的字节位移.
p2.recv_bytes_into(buffer [, offset])

先收后发,其实我们完全可以使用锁来控制它的首发,可以让它一边收一边发。

队列

队列与其它不同的是它采取插入和删除的方法,让我们来看下:

def fd(a):
    for y in range(10):
        a.put(y)  #插入数据
        print('插入:',str(y))
def df(b):
    while True:
        aa=b.get(True) #删除数据
        print('释放:',str(aa))
if __name__ == '__main__':
    q=Queue()
    ff=Process(target=fd,args=(q,))
    dd=Process(target=df,args=(q,))
    ff.start() #开始运行
    dd.start()
    dd.terminate() #关闭
    ff.join()

以上讲的队列主要用于多进程的队列,还有一个进程池的队列,它在Manager模块中。

八、信号量

与线程中完全一样,这里不在赘述,看下例:

s=Semaphore(3)
s.acquire()
print(s.get_value())
s.release()
print(s.get_value())
print(s.get_value())
s.release()
print(s.get_value())
s.release()

output:
2
3
3
4

九、数据共享

共享数据类型可以直接通过进程模块来设置:

数值型:m.Value()
数组性:m.Array()
字典型:m.dict()
列表型:m.list()

也可以通过进程的Manager模块来实现:

Manager().dict()
Manager.list()

下面我们就来举例说明下吧:

可以看到我们成功的将数据添加了进去,形成了数据的共享。

十、总结

通过对进程的描述,相信大家对进程此刻有了个深刻的感悟了吧,突然想起个事,就是大家学习时可能查资料会在网上搜索,那么我建议你专心看好我这篇好了,因为据我所知,那些都是错的,而且更让我纳闷的是,明明代码是错的,放出来的执行效果却是对的,这让我百思不得其解,哈哈哈。

到此这篇关于Python基础之进程详解的文章就介绍到这了,更多相关Python进程内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 如何用tempfile库创建python进程中的临时文件

    技术背景 临时文件在python项目中时常会被使用到,其作用在于随机化的创建不重名的文件,路径一般都是放在Linux系统下的/tmp目录.如果项目中并不需要持久化的存储一个文件,就可以采用临时文件的形式进行存储和读取,在使用之后可以自行决定是删除还是保留. tempfile库的使用 tempfile一般是python内置的一个函数库,不需要单独安装,这里我们直接介绍一下其常规使用方法: # tempfile_test.py import tempfile file = tempfile.Name

  • python3中celery异步框架简单使用+守护进程方式启动

    安装celery sudo pip install celery 实例化 celery from celery import Celery app = Celery("testapp") # 导入配置 app.config_from_object('celery_tasks.config') # 自动添加任务 app.autodiscover_tasks(["celery_tasks.test","celery_tasks.test2"]) 简单

  • python 多进程和多线程使用详解

    进程和线程 进程是系统进行资源分配的最小单位,线程是系统进行调度执行的最小单位: 一个应用程序至少包含一个进程,一个进程至少包含一个线程: 每个进程在执行过程中拥有独立的内存空间,而一个进程中的线程之间是共享该进程的内存空间的: 计算机的核心是CPU,它承担了所有的计算任务.它就像一座工厂,时刻在运行. 假定工厂的电力有限,一次只能供给一个车间使用.也就是说,一个车间开工的时候,其他车间都必须停工.背后的含义就是,单个CPU一次只能运行一个任务.编者注: 多核的CPU就像有了多个发电厂,使多工厂

  • Python Process创建进程的2种方法详解

    前面介绍了使用 os.fork() 函数实现多进程编程,该方法最明显的缺陷就是不适用于 Windows 系统.本节将介绍一种支持 Python 在 Windows 平台上创建新进程的方法. Python multiprocessing 模块提供了 Process 类,该类可用来在 Windows 平台上创建新进程.和使用 Thread 类创建多线程方法类似,使用 Process 类创建多进程也有以下 2 种方式: 直接创建 Process 类的实例对象,由此就可以创建一个新的进程: 通过继承 P

  • python多线程和多进程关系详解

    关于多线程的大概讲解: 在Python的标准库中给出了2个模块:_thread和threading,_thread是低级模块不支持守护线程,当主线程退出了时,全部子线程都会被强制退出了.而threading是高级模块,用作对_thread进行了封装支持守护线程.在大部分状况下人们只需要采用threading这个高级模块即可. 关于多进程的大概讲解: 多进程是multiprocessing模块给出远程与本地的并发,在一个multiprocessing库的采用场景下,全部的子进程全是由一个父进程运行

  • python实现启动一个外部程序,并且不阻塞当前进程

    python可以使用os模块中的system函数来启动外部程序. Windows平台下使用start命令就可以不阻塞当前进程的执行程序,测试代码如下: import os os.system('start calc') 补充知识:Python:启动大量子进程 我就废话不多说了,大家还是直接看代码吧~ #!/usr/bin/env python # coding:UTF-8 """ @version: python3.x @author:曹新健 @contact: 617349

  • 解决Python 进程池Pool中一些坑

    1 from multiprocessing import Pool,Queue. 其中Queue在Pool中不起作用,具体原因未明. 解决方案: 如果要用Pool创建进程,就需要使用multiprocessing.Manager()中的Queue, 与multiprocessing中的Queue不同 q=Manager().Queue()#Manager中的Queue才能配合Pool po = Pool() # 无穷多进程 2 使用进程池,在进程中调用io读写操作. 例如: p=Pool()

  • 如何用 Python 子进程关闭 Excel 自动化中的弹窗

    利用Python进行Excel自动化操作的过程中,尤其是涉及VBA时,可能遇到消息框/弹窗(MsgBox).此时需要人为响应,否则代码卡死直至超时 [^1] [^2].根本的解决方法是VBA代码中不要出现类似弹窗,但有时我们无权修改被操作的Excel文件,例如这是我们进行自动化测试的对象.所以本文记录从代码角度解决此类问题的方法. 假想场景 使用xlwings(或者其他自动化库)打开Excel文件test.xlsm,读取Sheet1!A1单元格内容.很简单的一个操作: import xlwing

  • Python之多进程与多线程的使用

    进程与线程 想象在学校的一个机房,有固定数量的电脑,老师安排了一个爬虫任务让大家一起完成,每个学生使用一台电脑爬取部分数据,将数据放到一个公共数据库.共同资源就像公共数据库,进程就像每一个学生,每多一个学生,就多一个进程来完成这个任务,机房里的电脑数量就像CPU,所以进程数量是CPU决定的,线程就像学生用一台电脑开多个爬虫,爬虫数量由每台电脑的运行内存决定. 一个CPU可以有多个进程,一个进程有一个或多个线程. 多进程 1.导包 from multiprocessing import Proce

  • Python 多进程原理及实现

    1 进程的基本概念 什么是进程? ​ 进程就是一个程序在一个数据集上的一次动态执行过程.进程一般由程序.数据集.进程控制块三部分组成.我们编写的程序用来描述进程要完成哪些功能以及如何完成:数据集则是程序在执行过程中所需要使用的资源:进程控制块用来记录进程的外部特征,描述进程的执行变化过程,系统可以利用它来控制和管理进程,它是系统感知进程存在的唯一标志. 进程的生命周期:创建(New).就绪(Runnable).运行(Running).阻塞(Block).销毁(Destroy) 进程的状态(分类)

  • python multiprocessing 多进程并行计算的操作

    python的multiprocessing包是标准库提供的多进程并行计算包,提供了和threading(多线程)相似的API函数,但是相比于threading,将任务分配到不同的CPU,避免了GIL(Global Interpreter Lock)的限制. 下面我们对multiprocessing中的Pool和Process类做介绍. Pool 采用Pool进程池对任务并行处理更加方便,我们可以指定并行的CPU个数,然后 Pool 会自动把任务放到进程池中运行. Pool 包含了多个并行函数.

  • python实现多进程并发控制Semaphore与互斥锁LOCK

    一.了解锁 应用场景举例描述: Lock 互斥锁:举例说明–有三个同事同时需要上厕所,但是只有一间厕所,将同事比作进程,多个进程并打抢占一个厕所,我们要保证顺序优先, 一个个来,那么就必须串行,先到先得,有人使用了,就锁住,结束后剩余的人继续争抢 1.利用Lock来处理 模拟三个同事抢占厕所 from multiprocessing import Process from multiprocessing import Lock import time import random def task

  • Selenium执行完毕未关闭chromedriver/geckodriver进程的解决办法(java版+python版)

    selenium操作chrome浏览器需要有ChromeDriver驱动来协助.webdriver中关浏览器关闭有两个方法,一个叫quit,一个叫close. /** * Close the current window, quitting the browser if it's the last window currently open. */ void close(); /** * Quits this driver, closing every associated window. */

  • python多进程执行方法apply_async使用说明

    apply_async简介 python在同一个线程中多次执行同一方法时,该方法执行耗时较长且每次执行过程及结果互不影响,如果只在主进程中执行,效率会很低,因此使用multiprocessing.Pool(processes=n)及其apply_async()方法提高程序执行的并行度从而提高程序的执行效率,其中processes=n为程序并行执行的进程数. apply_async使用简明代码 import multiprocessing #method为多次调用的方法 def method(pa

  • Python多进程与多线程的使用场景详解

    前言 Python多进程适用的场景:计算密集型(CPU密集型)任务 Python多线程适用的场景:IO密集型任务 计算密集型任务一般指需要做大量的逻辑运算,比如上亿次的加减乘除,使用多核CPU可以并发提高计算性能. IO密集型任务一般指输入输出型,比如文件的读取,或者网络的请求,这类场景一般会遇到IO阻塞,使用多核CPU来执行并不会有太高的性能提升. 下面使用一台64核的虚拟机来执行任务,通过示例代码来区别它们, 示例1:执行计算密集型任务,进行1亿次运算 使用多进程 from multipro

  • 像线程一样管理进程的Python multiprocessing库

    一.创建一个进程 要创建一个进程,最简单的方式是用一个目标函数实例化一个Process对象,然后与threading一样调用start()函数让它工作.示例如下: import multiprocessing def worker(): for i in range(3): print(i) if __name__=="__main__": p = multiprocessing.Process(target=worker) p.start() 运行之后,效果如下: 需要注意的是,mu

  • python 实现多进程日志轮转ConcurrentLogHandler

    记录日志是我们程序中必不可少的一个功能,但是日志文件如果没有合理的管理,时间长了几百兆的日志文件就很难分析了(都不想打开看),但是又不可能经常手动去管理它 日志轮转:根据时间或者文件大小控制日志的文件个数,不用我们手动管理 python中logging模块内置的有几个支持日志轮转的handler 常用的有TimedRotatingFileHandler根据时间轮转 RotatingFileHandler根据文件大小轮转 但是内置的这些handler是多线程安全的,而不支持多进程(可以修改源码加锁

  • Python中使用subprocess库创建附加进程

    前言 subprocess库提供了一个API创建子进程并与之通信.这对于运行生产或消费文本的程序尤其有好处,因为这个API支持通过新进行的标准输入和输出通道来回传数据. 本篇,将详细介绍Python创建附加进行的库:subprocess. run(运行外部命令) subprocess库本身可以替换os.system(),os.spawnv()等函数.现在我们来通过subprocess库运行一个外部命令,但不采用os.system().示例如下: import subprocess complet

随机推荐