Python进程-实现
fork介绍
Unix/Linux操作系统提供了一个fork()
系统调用,它非常特殊。普通的函数调用,调用一次,返回一次,但是fork()
调用一次,返回两次,因为操作系统自动把当前进程(称为父进程)复制了一份(称为子进程),然后,分别在父进程和子进程内返回。
子进程永远返回0
,而父进程返回子进程的ID。这样做的理由是,一个父进程可以fork出很多子进程,所以,父进程要记下每个子进程的ID,而子进程只需要调用getppid()
就可以拿到父进程的ID。
Python的os
模块封装了常见的系统调用
import os if __name__ == '__main__': print('进程 (%s) start...' % os.getpid())
pid = os.fork()
# time.sleep(10)
if pid == 0: # 子进程fork()返回0
print("子进程{},父进程{}".format(os.getpid(), os.getppid()))
else: # 父进程fork返回子进程的id
print("父进程{},子进程{}".format(os.getpid(), pid)) --》》结果
进程 (3130) start...
父进程3130,子进程3131
子进程3131,父进程3130
multiprocessing模块介绍
python中的多线程无法利用CPU资源,在python中大部分计算密集型任务使用多进程。如果想要充分地使用多核CPU的资源(os.cpu_count()查看)
python中提供了非常好的多进程包multiprocessing。
multiprocessing模块用来开启子进程,并在子进程中执行功能(函数),该模块与多线程模块threading的编程接口类似。
multiprocessing的功能众多:支持子进程、通信和共享数据、执行不同形式的同步,提供了Process、Queue、Pipe、Lock等组件。
计算密集型任务:如金融分析,科学计算
注意
记住,进程的执行是有操作系统调度的,python执行进程(start)只是向操作系统发信号,告诉操作系统,我要开辟一个进程,由操作系统调度执行。
同理,python终止进程(terminate)只是向操作系统发信号,告诉操作系统,我要终止一个进程,而不会马上终止,由操作系统调度终止进程。
Process类的介绍
1.创建进程的类
Process([group [, target [, name [, args [, kwargs]]]]]),由该类实例化得到的对象,表示一个子进程中的任务(尚未启动) 强调:
1. 需要使用关键字的方式来指定参数
2. args指定的为传给target函数的位置参数,是一个元组形式,必须有逗号
2.参数介绍
group参数未使用,值始终为None target表示调用对象,即子进程要执行的任务 args表示调用对象的位置参数元组,args=(1,2,'al',) kwargs表示调用对象的字典,kwargs={'name':'al','age':18} name为子进程的名称
3.方法介绍
p.start():启动进程,并调用该子进程中的p.run()
p.run():进程启动时运行的方法,正是它去调用target指定的函数,我们自定义类的类中一定要实现该方法 p.terminate():强制终止进程p,不会进行任何清理操作,如果p创建了子进程,该子进程就成了僵尸进程,使用该方法需要特别小心这种情况。
如果p还保存了一个锁那么也将不会被释放,进而导致死锁
p.is_alive():如果p仍然运行,返回True p.join([timeout]):主线程等待p终止(强调:是主线程处于等的状态,而p是处于运行的状态)。timeout是可选的超时时间,
需要强调的是,p.join只能join住start开启的进程,而不能join住run开启的进程
4.属性介绍
p.daemon:默认值为False,如果设为True,代表p为后台运行的守护进程,当p的父进程终止时,p也随之终止,并且设定为True后,p不能创建自己的新进程,必须在p.start()之前设置 p.name:进程的名称 p.pid:进程的pid p.exitcode:进程在运行时为None、如果为–N,表示被信号N结束(了解即可) p.authkey:进程的身份验证键,默认是由os.urandom()随机生成的32字符的字符串。这个键的用途是为涉及网络连接的底层进程间通信提供安全性,
这类连接只有在具有相同的身份验证键时才能成功(了解即可)
Process类的使用
注意:在windows中Process()必须放到# if __name__ == '__main__':下
开一个进程和主进程是并发的关系,我start一下就是先告诉操作系统我要开一个进程
,然而它不会等待,他会去执行下面的代码,完了他把进程开始后,就开始执行了
# window创造进程相当于导入,会无线递归创建
# Linux 是把父进程拷贝到子进程
import multiprocessing
import time
import threading print('main process start1')
def func():
print('subprocess start',time.asctime(time.localtime(time.time())))
time.sleep(3)
print('subprocess end',time.asctime(time.localtime(time.time()))) print('main process start2')
p = multiprocessing.Process(target=func, name='1号')
p.start()
print('main process end', time.asctime(time.localtime(time.time())),multiprocessing.current_process())
if __name__ == '__main__':
pass
# 默认所有进程结束后,程序才结束 """
linux
main process start1
main process start2
main process end Fri Mar 23 00:20:29 2018 <_MainProcess(MainProcess, started)>
subprocess start Fri Mar 23 00:20:29 2018
subprocess end Fri Mar 23 00:20:32 2018 """ """
windows
Make sure that the main module can be safely
imported by a new Python interpreter without causing unintended
side effects (such a starting a new process)." main process start1
main process start2
main process end Fri Mar 23 00:23:50 2018 <_MainProcess(MainProcess, started)>
main process start1 #相当于导入一次该程序,在main函数之前调用进程,会造成无限循环输出导致报错
subprocess start Fri Mar 23 00:23:50 2018
subprocess end Fri Mar 23 00:23:53 2018 """
strat():方法的功能
1.开启进程
2.执行功能
开启进程方法一
import time
import multiprocessing
# import threading def func():
i = 0
for _ in range(10000000):
i += 1
return True def main():
start = time.time()
p = multiprocessing.Process(target=func) # 创建一个子进程
p1 = multiprocessing.Process(target=func)
p.start()
p1.start()
# p = threading.Thread(target=func)
# p.start()
func()
end = time.time()
print(end - start) if __name__ == '__main__':
main()
开启进程方法二
from multiprocessing import Process
import time
import random
import os
class pro(Process):
def __init__(self,name):
super().__init__() # 必须继承父类的一些属性
self.name = name
def run(self): # 必须得实现一个run方法
print('%s is work,父进程%s,当前进程%s'%(self.name,os.getppid(),os.getpid()))
time.sleep(1)
print('%s is work end'%self.name)
if __name__ =='__main__':
p1 = pro('al')
p2 = pro('b1')
p3 = pro('c1')
p1.start()
p2.start()
p3.start()
print('主进程',os.getpid()) -》》输出
主进程 9116
b1 is work,父进程9116,当前进程4316
al is work,父进程9116,当前进程6664
c1 is work,父进程9116,当前进程10132
b1 is work end
al is work end
c1 is work end
使用daemon
- 守护进程会在主进程代码执行结束后就终止
from multiprocessing import Process
import time
import random
import os
class My_Process(Process):
def __init__(self,name):
super().__init__() # 必须继承父类的一些属性
self.name = name def run(self): # 必须得实现一个run方法
time.sleep(5)
print('%s is work end'%self.name) if __name__ =='__main__':
start_time = time.time()
print("process start")
for i in range(5):
t = My_Process('Process%s' % i)
# t.daemon = True
t.start()
time.sleep(3)
print("process end")
print(time.time() - start_time) """
t.daemon = False
process start
process end #主进程运行完毕后,程序等待子进程运行完成后结束
0.020070791244506836
Process0 is work end
Process2 is work end
Process3 is work end
Process4 is work end
Process1 is work end Process finished with exit code 0
""" """
t.daemon = True
process start
process end #主进程运行完毕后,守护进程结束
3.014104127883911 Process finished with exit code 0
"""
2. 守护进程内无法再开启子进程,否则抛出异常:AssertionError: daemonic processes are not allowed to have children
from multiprocessing import Process
import time
import random def task(name):
print('%s is start' %name)
time.sleep(random.randrange(1,3))
print('%s is end' %name)
p = Process(target=time.sleep, args=(3,)) #在守护进程里面开子进程报错
p.start() if __name__ == '__main__':
p=Process(target=task,args=('egon',))
p.daemon=True #一定要在p.start()前设置,设置p为守护进程,禁止p创建子进程,并且父进程代码执行结束,p即终止运行 p.start()
p.join()
print('主') #只要终端打印出这一行内容,那么守护进程p也就跟着结束掉了
----------- egon is start
egon is end
Process Process-1:
Traceback (most recent call last):
File "C:\Program Files\Python36\lib\multiprocessing\process.py", line 249, in _bootstrap
self.run()
File "C:\Program Files\Python36\lib\multiprocessing\process.py", line 93, in run
self._target(*self._args, **self._kwargs)
File "C:\Users\jingjing\PycharmProjects\py3Project\路飞\第四模块课件\01网络编程进阶\01 多进程\05 守护进程.py", line 55, in task
p.start()
File "C:\Program Files\Python36\lib\multiprocessing\process.py", line 103, in start
'daemonic processes are not allowed to have children'
AssertionError: daemonic processes are not allowed to have children
主
思考下列代码的执行结果有可能有哪些情况?为什么?
from multiprocessing import Process import time
def foo():
print(123)
time.sleep(1)
print("end123") def bar():
print(456)
time.sleep(3)
print("end456") if __name__ == '__main__':
p1=Process(target=foo)
p2=Process(target=bar) p1.daemon=True
p1.start()
p2.start()
print("main-------") -----输出
main-------
456
end456
当输出main之后,守护进程就结束了
使用terminate
import multiprocessing
import time
import threading def func():
print('subprocess start',time.asctime(time.localtime(time.time())))
time.sleep(3)
print('subprocess end',time.asctime(time.localtime(time.time()))) if __name__ == '__main__':
p = multiprocessing.Process(target=func, name='1号')
p.start()
p.terminate() # 终止进程
time.sleep(5)
print(p.is_alive()) # 判断这个进程是否存在
# 默认所有进程结束后,程序才结束
print('main process end', time.asctime(time.localtime(time.time())), multiprocessing.current_process())
-》》》输出
"""
False 终止进程后is_alive()返回False,没有执行print('subprocess s……
main process end Fri Mar 23 17:22:57 2018 <_MainProcess(MainProcess, started)>
"""
使用join
import multiprocessing
import time
import threading def func():
print('subprocess start',time.asctime(time.localtime(time.time())))
time.sleep(3)
print('subprocess end',time.asctime(time.localtime(time.time()))) if __name__ == '__main__':
p = multiprocessing.Process(target=func, name='1号')
p.start()
p.join() # 等待子进程完成后,结束主线程
# 默认所有进程结束后,程序才结束
print('main process end', time.asctime(time.localtime(time.time())), multiprocessing.current_process()) """
不使用join
# 主线程调用子线程后直接结束,然后子线程再结束
main process end Fri Mar 23 17:34:01 2018 <_MainProcess(MainProcess, started)>
subprocess start Fri Mar 23 17:34:01 2018
subprocess end Fri Mar 23 17:34:04 2018
""" """
使用join
subprocess start Fri Mar 23 17:30:20 2018
subprocess end Fri Mar 23 17:30:23 2018
# 等待子进程完成后,结束主线程
main process end Fri Mar 23 17:30:23 2018 <_MainProcess(MainProcess, started)>
"""
join用法考题
类似于单进程
from multiprocessing import Process
import time def task(n, t):
time.sleep(t)
print('-------->%s' %n) if __name__ == '__main__':
p1=Process(target=task,args=(1,5))
p2=Process(target=task,args=(2,2))
p3=Process(target=task,args=(3,1))
start = time.time()
p1.start()
p1.join()
p2.start()
p2.join()
p3.start()
p3.join() print('-------->time', time.time() - start) ------------------输出-----相当于单进程,时间等于3个进程执行时间的相加
-------->1
-------->2
-------->3
-------->time 9.534545183181763
类似于多进程
from multiprocessing import Process
import time def task(n, t):
time.sleep(t)
print('-------->%s' %n) if __name__ == '__main__':
p1=Process(target=task,args=(1,5))
p2=Process(target=task,args=(2,2))
p3=Process(target=task,args=(3,1))
start = time.time()
p_l = [p1,p2,p3]
for p in p_l:
p.start() for p in p_l:
p.join() print('--------4 >time', time.time() - start) ---------------输出------------相当于多进程,执行时间等于最长进程的执行时间
-------->3
-------->2
-------->1
--------4 >time 5.624321699142456
使用多进程实现并发的服务器
服务器端
import socket
import multiprocessing
server = socket.socket()
server.bind(('127.0.0.1', 9988))
server.listen(5) def read_msg(conn, addr):
while True:
try:
data = conn.recv(1024)
if data: # 正常接收数据
print('收到{}:数据{}'.format(addr,data.decode()))
conn.send(data)
else: # 收到空消息,关闭
print('close:{}'.format(addr))
break
except Exception as e:
print(e)
break
conn.close() if __name__ == '__main__':
while True:
print('-------主进程,等待连接------')
conn, addr = server.accept()
print('创建一个新的进程,和客户端{}通信'.format(addr))
client= multiprocessing.Process(target=read_msg, args=(conn, addr))
# client = threading.Thread(target=readable, args=((conn, addr)))
# p.start()
client.start()
server.close()
客户端
# 客户端
import socket # 导入socket模块 socket_client = socket.socket() # 创建监听套接字
socket_client.connect(('127.0.0.1', 9988)) # 连接套接字 ,要连接的IP与端口 while 1:
cmd = input("Please input cmd:") # 与人交互,输入命令
if not cmd: continue
elif cmd == 'q':break
socket_client.send(cmd.encode('utf-8')) # 把命令发送给服务端
data = socket_client.recv(1024)
print('recv',data) socket_client.close()
练习题
from multiprocessing import Process n=100 #在windows系统中应该把全局变量定义在if __name__ == '__main__'之上就可以了 def work():
global n
n=0
print('子进程内: ',n) if __name__ == '__main__':
p=Process(target=work)
p.start()
print('主进程内: ',n) 进程之间的内存空间是共享的还是隔离的?上述代码的执行结果是什么?
进程之间的内存空间是隔离的
执行结果:
主进程内: 100
子进程内: 0
改写下列程序,分别别实现下述打印效果
from multiprocessing import Process
import time
import random def task(n):
time.sleep(random.randint(1,3))
print('-------->%s' %n) if __name__ == '__main__':
p1=Process(target=task,args=(1,))
p2=Process(target=task,args=(2,))
p3=Process(target=task,args=(3,)) p1.start()
p2.start()
p3.start() print('-------->4')
效果一:保证最先输出-------->4
from multiprocessing import Process
import time
import random def task(n):
time.sleep(random.randint(1,3))
print('-------->%s' %n) if __name__ == '__main__':
p1=Process(target=task,args=(1,))
p2=Process(target=task,args=(2,))
p3=Process(target=task,args=(3,)) p1.start()
p2.start()
p3.start() print('-------->4') ----------输出
-------->4
-------->1
-------->3
-------->2
效果二:保证最后输出-------->4
from multiprocessing import Process
import time
import random def task(n):
time.sleep(random.randint(1,3))
print('-------->%s' %n) if __name__ == '__main__':
p1=Process(target=task,args=(1,))
p2=Process(target=task,args=(2,))
p3=Process(target=task,args=(3,)) p1.start()
p2.start()
p3.start() p1.join()
p2.join()
p3.join()
print('-------->4')
----------------------------输出
-------->1
-------->3
-------->2
-------->4
效果三:保证按顺序输出
from multiprocessing import Process
import time
import random def task(n):
time.sleep(random.randint(1,3))
print('-------->%s' %n) if __name__ == '__main__':
p1=Process(target=task,args=(1,))
p2=Process(target=task,args=(2,))
p3=Process(target=task,args=(3,)) p1.start()
p1.join()
p2.start()
p2.join()
p3.start()
p3.join() print('-------->4') -------------------------输出
-------->1
-------->2
-------->3
-------->4
2、判断上述三种效果,哪种属于并发,哪种属于串行?
第一种和第二种属于并发,最后一种属于并行
Python进程-实现的更多相关文章
- python——进程基础
我们现在都知道python的多线程是个坑了,那么多进程在这个时候就变得很必要了.多进程实现了多CPU的利用,效率简直棒棒哒~~~ 拥有一个多进程程序: #!/usr/bin/env python #- ...
- 使用gdb调试Python进程
使用gdb调试Python进程 有时我们会想调试一个正在运行的Python进程,或者一个Python进程的coredump.例如现在遇到一个mod_wsgi的进程僵死了,不接受请求,想看看究竟是运行到 ...
- python进程、线程、协程(转载)
python 线程与进程简介 进程与线程的历史 我们都知道计算机是由硬件和软件组成的.硬件中的CPU是计算机的核心,它承担计算机的所有任务. 操作系统是运行在硬件之上的软件,是计算机的管理者,它负责资 ...
- Python进程、线程、协程详解
进程与线程的历史 我们都知道计算机是由硬件和软件组成的.硬件中的CPU是计算机的核心,它承担计算机的所有任务. 操作系统是运行在硬件之上的软件,是计算机的管理者,它负责资源的管理和分配.任务的调度. ...
- python进程池剖析(一)
python中两个常用来处理进程的模块分别是subprocess和multiprocessing,其中subprocess通常用于执行外部程序,比如一些第三方应用程序,而不是Python程序.如果需要 ...
- python——进程、线程、协程
Python线程 Threading用于提供线程相关的操作,线程是应用程序中工作的最小单元. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 #!/usr/bin/env pytho ...
- python/进程线程的总结
python/进程线程的总结 一.进程和线程的描述: 进程:最小的资源管理单位 线程:最小的执行单位 执行一个进程时就默认执行一个线程(主线程) 进程和线程的工作方式: 串行: 假如共有A.B.C任务 ...
- python 进程介绍 进程简单使用 join 验证空间隔离
一.多道程序设计技术(详情参考:https://www.cnblogs.com/clschao/articles/9613464.html) 所谓多道程序设计技术,就是指允许多个程序同时进入内存并运行 ...
- Python 进程之间共享数据
最近遇到多进程共享数据的问题,到网上查了有几篇博客写的蛮好的,记录下来方便以后查看. 一.Python multiprocessing 跨进程对象共享 在mp库当中,跨进程对象共享有三种方式,第一种 ...
- python进程、多进程
进程: 进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础.在早期面向进程设计的计算机结构中,进程是程序的基本执行实体:在当 ...
随机推荐
- hihoCoder 1051 : 补提交卡 枚举
思路:预处理cnt(i)表示前i个数中有多少天需要补提交卡,枚举各个连续区间,区间[j, i]中需要补提交卡的天数是cnt(i) - cnt(j-1),判断m是否大于等于cnt(i) - cnt(j- ...
- 设置TCP_USER_TIMEOUT参数来判断tcp连接是否断开
[TOC] 1. bug描述 前段时间遇到这样的一个问题,openstack一个控制节点宕机后,在宕机后一段时间内创建的虚拟机,一直卡在创建中的状态.有的甚至要等到16分钟之后虚拟机才会切换到下一个状 ...
- mysql 主从同步 mysql代理服务器
搭建mysql主从同步(实现数据自动备份)实例:把主机192.168.4.100的数据库配置为主机192.168.4.99的从数据库 主数据库服务器配置修改配置文件: [root@mysql ~]# ...
- freemarker写select组件(五)
freemarker写select组件 1.宏定义 <#macro select id datas value="" key="" text=" ...
- freemarker写select组件(二)
freemarker写select组件 1.宏定义 <#macro select id datas value=""> <select id="${id ...
- 动态链接库(DLL)
DLL 的类型 当您在应用程序中加载 DLL 时,可以使用两种链接方法来调用导出的 DLL 函数.这两种链接方法是加载时动态链接和运行时动态链接. 加载时动态链接 在加载时动态链接中,应用程序像调用本 ...
- C#技术点--修改系统时间
C#的System.DateTime类提供了对日期时间的封装,用它进行时间的转换和处理很方便,但是我没有在其中找到任何可以用来修改系统时间的成员.用过VC.VB等的朋友可能知道,我们可以调用Win32 ...
- Xshell配色为ubuntu风格
背景 为了远程连接服务器,用Xshell作为连接工具,因为好(mian)用(fei),服务器是ubuntu的,因此看不习惯Xshell自带的黑白色,下面给出了ubuntu的配色方案,使用的时候直接导入 ...
- RobotFramework下的http接口自动化Get Response Status 关键字的使用
Get Response Status 关键字用来获取http请求返回的http状态码. 示例1:访问苏宁易购网站上的http推荐接口,使用Get Response Status 关键字来获取返回的h ...
- Ubantu16.04进行Android 8.0源码编译
参考这篇博客 经过测试,8.0源码下载及编译之后,占用100多G的硬盘空间,尽量给ubantu系统多留一些硬盘空间,如果后续需要在编译好的源码上进行开发,需要预留更多的控件,为了防止后续出现文件权限问 ...