python学习笔记22
python学习笔记22
multiprocessing模块
from multiprocessing import Process
import os
# getpid()获取进程id
# getppid()获取父进程id
def func():
print(os.getpid(),os.getppid())
if __name__ == '__main__':
print('main:',os.getpid(),os.getppid())
p = Process(target=func)
p.start() # 开启一个子进程
## main: 3804 17852
## 4152 3804
# 首先main后面打印的是主进程(即这个程序)的进程id和父进程id
# 后面打印出来的是主进程内开启的子进程的进程id和父进程id
Process类
关于上面的代码,有几个问题:
-
为什么要使用
if __name__ == '__main__'?进程之间的所有内存是隔离的。
在Windows操作系统中,开启子进程后总是import父进程所在的文件。如上程序中,
p.start()开启一个子进程后,子进程先导入父进程所在的文件,就将os模块、multiprocessing模块中的Process类和func函数全导入进子进程所在的内存空间。之后再执行func函数就是执行的父进程导入的func函数。所以if __name__ == '__main__'后的所有代码只会在主进程中执行而不会在子进程中执行(即避免了陷入不断创建子进程的死循环)。 -
能不能给子进程传递参数?
是可以的。在Process实例化的时候可以在参数里设置,如
p = Process(target=func,args=(a,b,c,d))这里的参数设置必须是一个元组。 -
能否获取子进程的返回值?
这里是不能获取的。当子进程真正开启时,父进程和子进程的内存就隔离了。
-
能否同时开启多个子进程?
这个是可以的。
if __name__ == '__main__': print('main:',os.getpid(),os.getppid()) p = Process(target=func) p.start() # 开启一个子进程 p1 = Process(target=func) p1.start() # 开启第二个子进程 p2 = Process(target=func) p2.start() # 开启第三个子进程 #... # 这里开启多个子进程的操作是并发异步执行的 # p.start()是一个典型的异步非阻塞的程序代码
join的用法
from multiprocessing import Process
import os
# getpid()获取进程id
# getppid()获取父进程id
def func():
print('正在执行')
if __name__ == '__main__':
print('开始执行')
p = Process(target=func)
p.start() # 开启一个子进程
print('执行完毕')
# 如果直接运行,结果为:
"""
开始执行
执行完毕
正在执行
"""
# 这是因为程序在开启子进程后并未停顿,直接运行后续代码
# 只需在开启子进程后加入代码p.join()
# 就可以让程序停顿直到子进程执行完毕
if __name__ == '__main__':
print('开始执行')
p = Process(target=func)
p.start() # 开启一个子进程
p.join() # 阻塞:直到子进程执行完毕才继续执行后续代码
print('执行完毕')
"""
开始执行
正在执行
执行完毕
"""
#### 当有多个子进程时,需要等所有子进程全部开启之后再对每个子进程进行join()
同步阻塞、异步非阻塞
同步阻塞的例子:上面使用的join函数
异步非阻塞的例子:上面使用的start函数
使用多进程实现一个并发的socket的server端
# Server端
import socket
from multiprocessing import Process
def talk(conn):
while True:
msg = conn.recv(1024).decode('utf-8')
ret = msg.upper().encode('utf-8')
conn.send(ret)
conn.close()
if __name__ == '__main__':
sk = socket.socket()
sk.bind(('127.0.0.1',9004))
sk.listen()
while True:
conn,addr = sk.accept() # 接收一个连接就开启一个子进程
Process(target=talk,args=(conn,)).start()
sk.close()
# Client端
import socket
sk = socket.socket()
sk.connect(('127.0.0.1',9004))
while True:
sk.send(b'hello')
msg = sk.recv(1024).decode('utf-8')
print(msg)
sk.close()
这时候的Server端就是通过一个简单的子进程实现了接收并发客户端消息的功能。

浙公网安备 33010602011771号