Python----进程

1、创建一个进程

Process(target=目标函数名, args=参数)  和 线程的接口类似。许多方法也是类似的。

from multiprocessing import Process
import time
def check(name):
    time.sleep(3)
    print("{}".format(name))

def age(x):
    time.sleep(6)
    print(x)

# 必须加上这句话,主进程
if __name__ == '__main__':
    p = Process(target=check, args=('Jax',))
    p1 = Process(target=age, args=(19,))
    p.start()
    p1.start()   #   激活进程
    print(p.pid) #   打印进程号
    p.join()     #   阻塞主进程,直到子进程结束,等待子进程的退出
    p1.join()
    print(p.name)  #   进程名
    print(p.is_alive())  #   进程是否存活
    

还可以通过继承的方式来实例进程对象。

from multiprocessing import Process


class MyProcess(Process):
    def run(self):
        print(self.name)

if __name__ == '__main__':  #  必须写上,保证是主进程

    p = MyProcess()
    p1 = MyProcess()
    p.start()
    p1.start()

2、守护进程

子进程和主进程一同退出。当主进程退出时一同退出,不管子进程是否结束。如果有其中一个子进程没有设置相当于主进程仍然没有完,仍然会等待子进程结束。在进程中只能通过t.daemon = True来设置守护线程。

from multiprocessing import Process
import time
def check(name):
    time.sleep(3)
    print("{}".format(name))

def age(x):
    time.sleep(6)
    print(x)
if __name__ == '__main__':
    p = Process(target=check, args=('Jax',))
    p1 = Process(target=age, args=(19,))
    p1.daemon=True   #  设置守护进程
    p.start()
    p1.start()
    print("23233")

3、进程的pid

当前进程的父进程是编译器

from multiprocessing import Process
import os

def check(name):
    print("当前进程{}".format(os.getpid()))
    print("当前父进程{}".format(os.getppid()))
    print("--------------------------")
    
if __name__ == '__main__':
    check("Jax")
    p = Process(target=check, args=('Jax',))
    p.start()

>>> 当前进程8492
>>> 当前父进程9908
>>> --------------------------
>>> 当前进程8460
>>> 当前父进程8492
>>> --------------------------

4、进程通信

1、Pipe()管道:multiprocessing.Pipe()用来创建管道,返回两个连接对象,代表管道的两端,一般用于进程之间的通。
recv()接收消息,接收不到会等待,卡住。send()   发消息

from multiprocessing import Process,Pipe

def Foo(conn):
    print(conn.recv())
    conn.send("Ok")


if __name__ == '__main__':
    parent_conn,child_conn = Pipe()  #  返回两个管道连接
    print('---->',id(child_conn))
    p = Process(target=Foo,args=(child_conn,))  #  创建进程时将一个管道给子进程
    p.start()
    parent_conn.send("2333")
    print("收到子进程的消息"+parent_conn.recv())


>>> ----> 2765870483048
>>> 2333
>>> 收到子进程的消息Ok

2、进程队列: 进程之间都是相互独立的。

import multiprocessing


def Foo(q):
    q.put(2333)
    q.put('?')

if __name__ == '__main__':
    # 进程队列用于进程间的通信
    q = multiprocessing.Queue()
    # 创建子进程时就把队列传过去
    p = multiprocessing.Process(target=Foo,args=(q,))
    p.start()
    print(q.get())
    print(q.get())

不同进程通过队列通信。传递的队列 q 是数据复制得来的。

3、基于协程处理并行:greenlet 。

switch( [参数] )方法切换执行点。

from greenlet import greenlet

def check():
    print(56)
    # 跳到it函数,跳转的时候会保留上下文,再次切换回来时,继续执行
    gr2.switch()
    print(12)
    gr2.switch()

def it():
    print(34)
    gr1.switch()
    print(89)

if __name__ == '__main__':
    gr1 = greenlet(check)
    gr2 = greenlet(it)
    gr1.switch()

过程:先打印56再跳到 it 函数打印34在跳回12再次跳到 it 函数打印89。

4、Manager()

Python实现多进程间通信的方式有很多种,例如队列,管道等。但是这些方式只适用于多个进程都是源于同一个父进程的情况。
如果多个进程不是源于同一个父进程,只能用共享内存,信号量等方式,但是这些方式对于复杂的数据结构,例如Queue,dict,list等,使用起来比较麻烦,不够灵活。

from multiprocessing import Process,Manager

def Foo(l,d,n):
    d[n] = "0"
    d['2'] = "2"
    l.append(n)

if __name__ == '__main__':
    L = []
    # 上下文打开Manger(),不用写close()方法。
    with Manager() as manger:  # ------------>等价于manger = Manger()
        d = manger.dict()  # 创建一个字典
        l = manger.list()  # 创建一个列表
        for i in range(10):
            #  把列表,字典传过去
            p = Process(target=Foo,args=(l,d,i))
            p.start()
            L.append(p)
        for p in L:
            p.join()
        print(d)
        print(l)

>>> {2: '0', '2': '2', 3: '0', 6: '0', 1: '0', 7: '0', 0: '0', 4: '0', 5: '0', 8: '0', 9: '0'}
>>> [2, 3, 6, 1, 7, 0, 4, 5, 8, 9]

5、进程池

from multiprocessing import Process,Pool
import time


def Foo(i):
    time.sleep(1)
    print(i)
    return "ok"

# 回调函数需要有一个参数  是子进程return回去的值
def koo(x):
    print(x)


if __name__ == '__main__':
    pool = Pool(5)  #  最大连接数
    for i in range(100): 
        pool.apply_async(func=Foo, args=(i,), callback=koo)  # 异步进程池
        # pool.apply(func=Foo, args=(i,))   #  同步进程池
    pool.close()  #  close必须在join之前用
    pool.join()

multiprocessing.pool(process = 3) 进程池,process最大连接数,不写默认电脑cpu的核数。

close() 方法:关闭pool,使其不在接受新的任务 。

执行完close后不会有新的进程加入到pool,join函数等待所有进程。
terminate() 方法:结束工作进程,不再处理未完成的任务。直接结束。join() 方法:join方法要在close或terminate之后使用

阻塞就是花时间等待一个事物的响应,非阻塞是不花时间等待先往下进行,等到有响应再进行。

非阻塞进程池:pool.apply_async(func, (args, ),callback) 。  回调函数去打印记录,需要有一个参数,是子进程return回去的值。

回调函数:某个动作或函数执行结束成功之后再去执行的方法,
阻塞进程池:pool.apply()  同步

另外一种并发模块:

concurrent.futures模块,它提供了 ThreadPoolExecutor 和 ProcessPoolExecutor 两个类,实现了对 threading 和 multiprocessing

的更高级的抽象,对编写线程池/进程池提供了直接的支持。通常直接用这个进程池。

from concurrent.futures import ThreadPoolExecutor  # 线程池
import time

def conn(arg):
    print(arg)
    time.sleep(1)

pool = ThreadPoolExecutor(5)  # 创建一个线程池大小为5

for i in range(10):
    a = pool.submit(conn,i) # 调用conn方法
    print(a.result(),"-------")  # 打印当前的结果,如果写在这里就不再是并发,而是串行
    print(a.done())  # 显示当前线程是否结束

map方法返回一个迭代器,迭代器中的回调执行返回的结果有序的。

from concurrent.futures import ThreadPoolExecutor

li = ["2333", "6666", "00000","2333", "6666", "00000","2333", "6666", "00000"]

def conn(arg):
    print(arg)
    return arg

pool = ThreadPoolExecutor(5)
result = pool.map(conn, li)  # 此时result是个迭代器

for i in result:
    print(i)

 

6、有关进程的概念

进程开销高于线程.
进程就是一个程序在一个数据集上的一次动态执行过程。是最小的资源单位。
程序不运行永远不是进程。进程是由程序,数据集,进程控制块组成的。
进程控制块用来记录进程外部特征,描述进程的执行变化过程,系统可以利用它来控制和管理进程。

并行和并发:

并发:是指系统具有多个任务(动作)的能力。范围大。
并行:是指系统具 同时 有多个任务(动作)的能力。同时指的是唯一的时间节点,同一时刻。
并行是并发的子集。

同步和异步:

同步:当进程执行IO操作时(等待外部数据),等就是同步。
异步:等到数据接收成功再回来处理,不等就是异步。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值