
想要充分利用多核CPU资源,Python中大部分情况下都需要使用多进程,Python中提供了multiprocessing这个包实现多进程。multiprocessing支持子进程、进程间的同步与通信,提供了Process、Queue、Pipe、Lock等组件。
开辟子进程
multiprocessing中提供了Process类来生成进程实例
Process([group [, target [, name [, args [, kwargs]]]]])1
group分组,实际上不使用
target表示调用对象,你可以传入方法的名字
args表示给调用对象以元组的形式提供参数,比如target是函数a,他有两个参数m,n,那么该参数为args=(m, n)即可
kwargs表示调用对象的字典
name是别名,相当于给这个进程取一个名字
先来个小例子:
# -- coding:utf-8 --from multiprocessing import Process, Poolimport osimport timedef run_proc(wTime):n = 0
while n < 3: print "subProcess %s run," % osgetpid(), "{0}"format(timectime()) #获取当前进程号和正在运行是的时间
timesleep(wTime) #等待(休眠)
n += 1if __name__ == "__main__":
p = Process(target=run_proc, args=(2,)) #申请子进程
pstart() #运行进程
print "Parent process run subProcess is ", ppid print "Parent process end,{0}"format(timectime())12345678910111213141516171819
运行结果:
Parent process run subProcess is 30196
Parent process end,Mon Mar 27 11:20:21 2017
subProcess 30196 run, Mon Mar 27 11:20:21 2017
subProcess 30196 run, Mon Mar 27 11:20:23 2017
subProcess 30196 run, Mon Mar 27 11:20:25 2017
根据运行结果可知,父进程运行结束后子进程仍然还在运行,这可能造成僵尸( zombie)进程。
通常情况下,当子进程终结时,它会通知父进程,清空自己所占据的内存,并在内核里留下自己的退出信息。父进程在得知子进程终结时,会从内核中取出子进程的退出信息。但是,如果父进程早于子进程终结,这可能造成子进程的退出信息滞留在内核中,子进程成为僵尸(zombie)进程。当大量僵尸进程积累时,内存空间会被挤占。
有什么办法可以避免僵尸进程呢?
这里介绍进程的一个属性 deamon,当其值为TRUE时,其父进程结束,该进程也直接终止运行(即使还没运行完)。
所以给上面的程序加上pdeamon = true,看看效果。
# -- coding:utf-8 --from multiprocessing import Process, Poolimport osimport timedef run_proc(wTime):n = 0
while n < 3: print "subProcess %s run," % osgetpid(), "{0}"format(timectime())
timesleep(wTime)
n += 1if __name__ == "__main__":
p = Process(target=run_proc, args=(2,))
pdaemon = True #加入daemon
pstart() print "Parent process run subProcess is ", ppid print "Parent process end,{0}"format(timectime())1234567891011121314151617181920
执行结果:
Parent process run subProcess is 31856
Parent process end,Mon Mar 27 11:40:10 2017
这是问题又来了,子进程并没有执行完,这不是所期望的结果。有没办法将子进程执行完后才让父进程结束呢?
这里引入pjoin()方法,它使子进程执行结束后,父进程才执行之后的代码
# -- coding:utf-8 --from multiprocessing import Process, Poolimport osimport timedef run_proc(wTime):n = 0
while n < 3: print "subProcess %s run," % osgetpid(), "{0}"format(timectime())
timesleep(wTime)
n += 1if __name__ == "__main__":
p = Process(target=run_proc, args=(2,))
pdaemon = True
pstart()
pjoin() #加入join方法
print "Parent process run subProcess is ", ppid print "Parent process end,{0}"format(timectime())123456789101112131415161718192021
执行结果:
subProcess 32076 run, Mon Mar 27 11:46:07 2017
subProcess 32076 run, Mon Mar 27 11:46:09 2017
subProcess 32076 run, Mon Mar 27 11:46:11 2017
Parent process run subProcess is 32076
Parent process end,Mon Mar 27 11:46:13 2017
这样所有的进程就能顺利的执行了。
将进程定义成类
通过继承Process类,来自定义进程类,实现run方法。实例p通过调用pstart()时自动调用run方法。
如下:
# -- coding:utf-8 --from multiprocessing import Process, Poolimport osimport timeclass Myprocess(Process):def __init__(self, wTime):
Process__init__(self)
selfwTime = wTime def run(self):
n = 0
while n < 3: print "subProcess %s run," % osgetpid(), "{0}"format(timectime())
timesleep(selfwTime)
n += 1if __name__ == "__main__":
p = Myprocess(2)
pdaemon = True
pstart() #自动调用run方法
pjoin() print "Parent process run subProcess is ", ppid print "Parent process end,{0}"format(timectime())12345678910111213141516171819202122232425262728
执行结果和上一个例子相同。
创建多个进程
很多时候系统都需要创建多个进程以提高CPU的利用率,当数量较少时,可以手动生成一个个Process实例。当进程数量很多时,或许可以利用循环,但是这需要程序员手动管理系统中并发进程的数量,有时会很麻烦。这时进程池Pool就可以发挥其功效了。可以通过传递参数限制并发进程的数量,默认值为CPU的核数。
直接上例子:
# -- coding:utf-8 --from multiprocessing import Process,Poolimport os,timedef run_proc(name): ##定义一个函数用于进程调用for i in range(5):
timesleep(02) #休眠02秒
print 'Run child process %s (%s)' % (name, osgetpid())#执行一次该函数共需1秒的时间if __name__ =='__main__': #执行主进程
print 'Run the main process (%s)' % (osgetpid())
mainStart = timetime() #记录主进程开始的时间
p = Pool(8) #开辟进程池
for i in range(16): #开辟14个进程
papply_async(run_proc,args=('Process'+str(i),))#每个进程都调用run_proc函数,
#args表示给该函数传递的参数。
print 'Waiting for all subprocesses done '
pclose() #关闭进程池
pjoin() #等待开辟的所有进程执行完后,主进程才继续往下执行
print 'All subprocesses done'
mainEnd = timetime() #记录主进程结束时间
print 'All process ran %02f seconds' % (mainEnd-mainStart) #主进程执行时间123456789101112131415161718192021222324
执行结果:
开头部分
Run the main process (30920)
Waiting for all subprocesses done …
Run child process Process0 (32396)
Run child process Process3 (25392)
Run child process Process1 (28732)
Run child process Process2 (32436)
末尾部分:
Run child process Process15 (25880)
All subprocesses done
All process last 249 seconds
相关说明:
这里进程池对并发进程的限制数量为8个,而程序运行时会产生16个进程,进程池将自动管理系统内进程的并发数量,其余进程将会在队列中等待。限制并发数量是因为,系统中并发的进程不是越多越好,并发进程太多,可能使CPU大部分的时间用于进程调度,而不是执行有效的计算。
采用多进程并发技术时,就单个处理机而言,其对进程的执行是串行的。但具体某个时刻哪个进程获得CPU资源而执行是不可预知的(如执行结果的开头部分,各进程的执行顺序不定),这就体现了进程的异步性。
如果单个程序执行14次run_proc函数,那么它会需要至少16秒,通过进程的并发,这里只需要249秒,可见并发的优势。
Docker容器运行后,如何进入容器进行 *** 作呢?起初我是用SSH。如果只启动一个容器,用SSH还能应付,只需要将容器的22端口映射到本机的一个端口即可。当我启动了五个容器后,每个容器默认是没有配置SSH Server的,安装配置SSHD,映射容器SSH端口,实在是麻烦。 我发现很多Docker镜像都是没有安装SSHD服务的,难道有其他方法进入Docker容器? 有很多种方法,包括使用 docker attach 命令或 nsenter 工具等。 使用 attach 命令有时候并不方便。当多个窗口同时 attach 到同一个容器的时候,所有窗口都会同步显示。 nsenter 可以访问另一个进程的名字空间。 为了连接到容器,你还需要找到容器的第一个进程的 PID,可以通过下面的命令获取。 PID=$(docker inspect –format “{{ StatePid }}” <container>) //将<container>换成你的容器id 通过这个 PID,就可以连接到这个容器: $ nsenter –target $PID –mount –uts –ipc –net –pid 更简单的,建议大家下载 bashrc_docker,并将内容放到 bashrc 中。
用taskkill 结束进程的时候,为什么有的进程是拒绝访问怎么才能结束这样的进程呢像卡巴等杀毒的及一些系统组建是不能杀掉的 因为他们有监控程序段 而一般像杀毒软件之类可以用鼠标杀掉 而系统关键组件绝对不能杀 有的杀了可是会影响系统性能严重的将会 哦 没有严重的情况 很严重的进程绝对不允许杀 否则别人用cmd窗口就可以干死别人的系统。方法一:利用进程的PID结束进程
命令格式:ntsd -c q -p pid
命令范例: ntsd -c q -p 1332 (结束explorerexe进程)
范例详解:explorerexe的pid为1332,但是如何获取进程的pid呢?在CMD下输入TASKLIST就可以获取当前任务管理器所有进程的PID。或者打开任务管理器,在菜单栏,选择“查看”—“选择列”,在打开的选择项窗口中将“PID(进程标识符)”项选择钩上,这样任务管理器的进程中就会多出PID一项了。(PID的分配并不固定,是在进程启动是由系统随机分配的,所以进程每次启动的进程一般都不会一样。)
方法二:利用进程名结束进程
命令格式:ntsd -c q -pn exe (exe 为进程名,exe不能省)
命令范例:ntsd -c q -pn explorerexe
任何一种编程语言,启动进程和关闭进程都是跟 *** 作系统相关的 *** 作,python中与 *** 作系统打交道的话,推荐使用os模块。
ossystem() 函数可以启动一个进程,执行完之后返回状态码。
osfork() 复制一个进程,如果是子进程返回0,如果是父进程返回子进程的pid,使用这个函数的时候,建议你学习一下linux编程的知识。
ospopen 以管道的方式创建进程。
osspawnl 也可以创建进程,并能指定环境变量。
oskill(pid, sig) 关闭一个进程,pid是进程号,sig是信号。与fork配合使用,例如你刚才用fork创建了一个子进程,它的pid是11990, 那么调用
oskill( 11990, signalCTRL_BREAK_EVENT)
就以ctrl+c的方式杀死了这个进程。
另外还有一个模块multiprocessing,这个模块封装了很多创建进程和进程间通信的 *** 作,可以让你发挥多核的威力。
以上就是关于python怎么实现一个进程全部的内容,包括:python怎么实现一个进程、怎样在Python中 *** 作Docker容器、用taskkill 结束进程的时候,为什么有的进程是拒绝访问怎么才能结束这样的进程呢等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)