多进程

多进程

先来个辅助函数

from multiprocessing import Pool
import time, os, random
from functools import wraps


def timethis(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        start_time = time.time()
        res = func(*args, **kwargs)
        end_time = time.time()
        print(end_time - start_time)
        return res

    return wrapper

系统级别的

import os

# os.getpid() : 获取自己的集成ID
# os.getppid() : 获取父进程的ID

print(f'父进程的ID:{os.getppid()}')
print(f'自己的ID: {os.getpid()}')

pid = os.fork()
print(os.getpid())

进程这样写

import os
from multiprocessing import Process


def run():
    print('child', os.getpid())


if __name__ == '__main__':
    print(os.getpid())
    p = Process(target=run)
    p.start()
    p.join()

Lock – 同时只能有一个访问我!

from multiprocessing import Process, Lock
import time


def run(lock, title):
    time.sleep(1)
    print(title)
    with lock:
        time.sleep(1)
        print(title)


if __name__ == '__main__':
    lock = Lock()
    for i in range(10):
        Process(target=run, args=(lock, i)).start()

Pool – 进程很多的话,应该用进程池

调用join()方法会等待所有子进程执行完毕,调用join()之前必须先调用close(),调用close()之后就不能继续添加新的Process

@timethis
def main():
    print(os.getpid(),'main start ===============')
    p = Pool()
    for i in range(8):
        p.apply_async(run)
    p.close()
    p.join()
    print(os.getpid(), 'main end ==================')

进程池还有种写法

with Pool(processes=28) as p:
  res = p.map(f, range(1, 20))
  print(res)

subprocess – 但很多时候,调用的是外部进程

import subprocess

r = subprocess.call(['nslookup', 'www.python.org'])
print(r)

# 如果需要交互 , 通过communicate()方法输入

p = subprocess.Popen(['nslookup'], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
output, err = p.communicate(b'set q=mx\npython.org\nexit\n')
print(output.decode('utf8'))

Queue – 进程通信,用队列来搞一搞

from multiprocessing import Process, Queue
import os, random, time


def fwrite(q):
    print(os.getpid(), 'task runing ')
    products = list('qwertyuiopasdfghjklzxcvbnm')
    for i in range(3):
        time.sleep(1)
        v = random.choice(products)
        q.put(v)
        print(os.getpid(), f'write {v}')


def fread(q):
    print(os.getpid(), 'read running')
    while True:
        value = q.get(True)
        print(os.getpid(), f'read {value}')


if __name__ == '__main__':
    print(os.getpid(), '**' * 20)
    q = Queue()

    pw = Process(target=fwrite, args=(q,))
    pr = Process(target=fread, args=(q,))

    pw.start()
    pr.start()

    print('我早就执行了么?')

    # 下面这两句很精髓
    # 如果没有下面两句,主进程就一路执行到底。
    # 如果没有pw.join(), 主进程直接执行 pr.terminate() 干掉了读进程。
    # pw.join()把主进程阻塞在这里,写完之后,主进程继续。
    pw.join()
    pr.terminate()
    # time.sleep(4)
    # print('主进程休息了4秒')
    # print(pr.is_alive())
    # print(pw.is_alive())

死循环 子进程 永生?

子进程 设置为 daemon 进程

pr = Process(target=fread, args=(q,))

# 注意成死掉之后,daemon进程也就跟着死了。
pr.daemon = True
pr.start()

# 如果在 daemon 基础上加上这个,那么死循环的 子进程 又能永生了。
# pr.join()

强制终结子进程

pr.terminate()

最后再明确下

  • 主进程运行结束了,子进程还在运行。 子进程 会在 父进程 的尸体上 运行到结束。

    • 当然,主进程调用 子进程的terminate() 会强行带走 子进程
    • 或者,子进程设置为 daemon , 那么就会随着主进程死去。
  • Join()的意思是:“主进程停下,等我执行完,你再继续” 。

    子进程 join 函数会阻塞主进程,让主进程在这里停下,等自己结束再继续运行。

  • Pool() 的 apply是同步的,大家一个挨一个执行,先来后到,禁止插队!

    apply_async 是异步的。只要CPU空闲了,大家快去抢CPU啊!手快有手慢无!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值