开启子进程方法一


Process属于multiprocess中的一个类

  • 例1:
import os
from multiprocessing import Process  # 因为在内部做了一些操作所以可以直接拿到Process类,可以通过这个类启动进程
def func():
    print('子进程',os.getpid(), os.getppid())
if __name__ == '__main__':     # 只在windouws操作系统要写这句话,再linux和mac系统上不用写。
    print('主进程', os.getpid(), os.getppid())
    p = Process(target = func)  # 实例化Process类。创建进程对象。此时没有开启此进程,func函数再子进程中执行,而不是在主进程中执行。
    p.start()  # 开启进程

运行结果

主进程 14668 11392   # 主进程的id成了子进程的父进程
子进程 7616 14668   # 子进程和主进程同时运行。

在这里插入图片描述

为什么要写if __name__ == '__main__':
在这里插入图片描述

各个进程之间有什么特点
  1. 异步
  2. 数据隔离
    数据隔离问题:进程直接的数据是不同的数据隔离问题:进程直接的数据是不同的
import os
import time
from multiprocessing import Process
count = 100
def func():
    global count
    count -= 1
    print('子进程:', count)
if __name__ == '__main__':
    print('主进程', os.getpid(), os.getppid())
    p = Process(target=func)
    p.start()
    time.sleep(2)
    print('主进程:', count)

运行结果

主进程 14708 11392
子进程: 99
主进程: 100

在这里插入图片描述

import os
import time
from multiprocessing import Process

count = 100

def func():
    global count
    count -= 1
    print('子进程__name__:', __name__)

print('>>>',__name__)

if __name__ == '__main__':
    print('主进程', os.getpid(), os.getppid())
    p = Process(target=func)
    print('启动子进程')
    p.start()
    print('结束子进程')

运行结果

>>> __main__
主进程 7148 11392
启动子进程
结束子进程
>>> __mp_main__     # 由于windows执行子进程时执行了主进程中程序,所以打印了子进程的__name__,也就是子进程的空间名
子进程__name__: __mp_main__
父进程和子进程的关系

父进程只负责通知操作系统启动子进程
接下来的工作由操作系统接手,父进程继续执行
父进程执行完毕后并不会直接结束程序,
而是会等待所有的子进程都执行完毕之后才结束
父进程要负责回收子进程的资源。也就是告诉操作系统,子进程全部执行完毕,通知操作系统子进程全部执行完毕,叫操作系统释放命名空间或把变量清空等。只有主进程有权限通知操作系统的级别。

  • 例2:
from multiprocessing import Process
import time
def f(name):
    time.sleep(1)
    print('hello', name, time.ctime())
if __name__ == '__main__':
    p_list = []
    for i in range(3):
        p = Process(target=f, args=('laura',))
        p_list.append(p)
        p.start()
    for i in p_list:
        i.join()
    print('end')

运行结果:

hello laura Sat Sep 22 11:21:47 2018
hello laura Sat Sep 22 11:21:47 2018
hello laura Sat Sep 22 11:21:47 2018
end

实例:
原生socket写并发程序

server端
import socket

sk = socket.socket()  # sk对象
sk.bind(('127.0.0.1', 9000))
sk.listen()
while True:  # 循环接收连接
    conn, addr = sk.accept()  # 此时conn可以通信了。
    while True:  # 一直和别人send,recv,别人一直想和我连,我一直和另外一个人说话,这样就不能收到连接了。因为在里面的while True 不出来,外面的while True就执行不了了。
        conn.send(b'hello')
        print(conn.recv(1024))
        
# 解决方法:把跟别人聊天这件事情交给一个子进程做,这样第一个循环就可以实现了。

from multiprocessing import Process

def communicate(conn):
    while True:
        conn.send(b'hello')
        print(conn.recv(1024))
        
if __name__ == '__main__':
    sk = socket.socket()
    sk.bind(('127.0.0.1', 9000))
    sk.listen()

    while True:                                                              
        conn, addr = sk.accept()                                             
        Process(target=communicate, args=(conn,)).start()  # 由于这句是在主进程写的,并且不希望在子进程中循环下去。所以要加一个if __name__ == '__main__'

在这里插入图片描述

client端
import socket
sk = socket.socket()
sk.connect(('127.0.0.1', 9000))
while True:
    print(sk.recv(1024))   # 那边先send,所以先recieve
    sk.send(b'bye')
join同步控制

join属于Process类中的一个方法
模拟十个进程分别发送十封邮件

import time
import random
from multiprocessing import Process
def func(index):
    time.sleep(random.random())  # 0到1秒直接随机睡一会儿
    print('第%s个邮件已经发送完毕' % index)

if __name__ == '__main__':
    for i in range(10):
        Process(target=func, args=(i, )).start()  # 十个子进程异步执行,让十个进程分别发十个邮件。
    print('10个邮件已经发送完毕')  # 最为主进程我想知道我的十个进程已经执行完了

运行结果

10个邮件已经发送完毕  
第4个邮件已经发送完毕
第0个邮件已经发送完毕
第8个邮件已经发送完毕
第2个邮件已经发送完毕
第7个邮件已经发送完毕
第9个邮件已经发送完毕
第5个邮件已经发送完毕
第1个邮件已经发送完毕
第3个邮件已经发送完毕
第6个邮件已经发送完毕

由于主进程和子进程完全异步,所以同时打印出来了,如图
在这里插入图片描述
可我要的结果是子进程全部执行完了再打印这句话。
Procee类中的join方法能够帮助我们知道子进程是什么时候结束的。作用:阻塞直到p进程执行完毕就结束阻塞。
用join方法实现同步控制

import time
import random
from multiprocessing import Process
def func(index):
    time.sleep(random.randint(1, 3))  
    print('第%s个邮件已经发送完毕' % index)

if __name__ == '__main__':
    p = Process(target=func, args=(1, ))
    p.start()
    p.join()
    print('1个邮件已经发送完毕')

运行结果

1个邮件已经发送完毕
1个邮件已经发送完毕

在这里插入图片描述

现在让十个进程异步发邮件,所有进程发完邮件后,才打印所有邮件发送完毕。相当于主进程和n个子进程同步了。
join在哪个进程下面就会在等待哪个进程。

import time
import random
from multiprocessing import Process

def func(index):
    time.sleep(random.random())
    print('第%s个邮件已经发送完毕' % index)

if __name__ == '__main__':
    p_list = []
    for i in range(10):
        p = Process(target=func, args=(i, ))
        p.start()
        p_list.append(p)
    for p in p_list:
        p.join()  # 十个进程都开启了之后,这十个进程都要执行完才执行以下代码。
    print('10个邮件已经发送完毕')    # 一定是在最后才打印这句话

运行结果

2个邮件已经发送完毕
第4个邮件已经发送完毕
第1个邮件已经发送完毕
第9个邮件已经发送完毕
第3个邮件已经发送完毕
第6个邮件已经发送完毕
第7个邮件已经发送完毕
第5个邮件已经发送完毕
第8个邮件已经发送完毕
第0个邮件已经发送完毕
10个邮件已经发送完毕

例:输出资源,屏幕为进程间共享资源时。

from multiprocessing import Process, Lock
import time
def f(l, i):
    # with l:  # 加把锁把屏幕控制了,谁先拿到锁谁先在屏幕输出。相当于串行 # 加了with就不用l.acquire()和l.realease()了
    l.acquire()
    time.sleep(1)  # 运行了10秒,如果没有锁,运行时间不用1秒
    print('hello world %s' % i)
    l.release()

if __name__ == '__main__':
    print(time.time())
    lock = Lock()
    list1 = []
    for num in range(10):
        p = Process(target=f, args=(lock, num))
        p.start()
        list1.append(p)

    for i in list1:
        i.join()
    print(time.time())

运行结果

1537682507.537764
hello world 0
hello world 1
hello world 2
hello world 3
hello world 4
hello world 5
hello world 6
hello world 8
hello world 7
hello world 9
1537682517.8930845

猜你喜欢

转载自blog.csdn.net/weixin_42233629/article/details/82975184