Python process (进程)

Stella981
• 阅读 590

进程 (process)

进程是对各种资源管理的集合,包含对各种资源的调用、内存的管理、网络接口的调用 进程要操作 CPU 必须先启动一个线程,启动一个进程的时候会自动创建一个线程,进程里的第一个线程就是主线程 程序执行的实例 有唯一的进程标识符(pid)

multiprossing 模块

启动进程

示例:

import multiprocessing
import time


def process_run(n):
    time.sleep(1)
    print('process', n)


for i in range(10):
    p = multiprocessing.Process(target=process_run, args=(i, ))
    p.start()

所有进程都是由父进程启动的

示例:

import multiprocessing
import os


def show_info(title):
    print(title)
    print('module name:', __name__)
    print('parent process:', os.getppid())
    print('process id', os.getpid())
    print('\n\n')


def f(name):
    show_info('function f')
    print(name)


if __name__ == '__main__':
    show_info('main process line')
    p = multiprocessing.Process(target=f, args=('children process', ))
    p.start()

进程间通信

线程间共享内存空间,进程间只能通过其他方法进行通信

Queue

注意这个 Queue 不同于 queue.Queue Queue type using a pipe, buffer and thread 两个进程的 Queue 并不是同一个,而是将数据 pickle 后传给另一个进程的 Queue 用于父进程与子进程之间的通信或同一父进程的子进程之间通信


示例:

from multiprocessing import Process, Queue


def p_put(*args):
    q.put(args)
    print('Has put %s' % args)


def p_get(*args):
    print('%s wait to get...' % args)
    print(q.get())
    print('%s got it' % args)


q = Queue()
p1 = Process(target=p_put, args=('p1', ))
p2 = Process(target=p_get, args=('p2', ))
p1.start()
p2.start()

输出结果: Has put p1 p2 wait to get... ('p1',) p2 got it


换成 queue 示例:

from multiprocessing import Process
import queue


def p_put(*args):
    q.put(args)
    print('Has put %s' % args)


def p_get(*args):
    print('%s wait to get...' % args)
    print(q.get())
    print('%s got it' % args)


q = queue.Queue()
p1 = Process(target=p_put, args=('p1', ))
p2 = Process(target=p_get, args=('p2', ))
p1.start()
p2.start()

输出结果: Has put p1 p2 wait to get...


由于父进程启动子进程时是复制一份,所以每个子进程里也有一个空的队列,但是这些队列数据独立,所以 get 时会阻塞

Pipe

Pipe(管道) 是通过 socket 进行进程间通信的 所以步骤与建立 socket 连接相似: 建立连接、发送/接收数据(一端发送另一端不接受就会阻塞)、关闭连接 示例:

from multiprocessing import Pipe, Process


def f(conn):
    conn.send('send by child')
    print('child recv:', conn.recv())
    conn.close()


parent_conn, child_conn = Pipe()    # 获得 Pipe 连接的两端
p = Process(target=f, args=(child_conn, ))
p.start()
print('parent recv:', parent_conn.recv())
parent_conn.send('send by parent')
p.join()

输出结果: parent recv: send by child child recv: send by parent

进程间数据共享

Manager

Manager 实现的是进程间共享数据 支持的可共享数据类型:

list
dict
Value
Array
Namespace
Queue                 queue.Queue
JoinableQueue        queue.Queue
Event                 threading.Event
Lock                 threading.Lock
RLock                 threading.RLock
Semaphore             threading.Semaphore
BoundedSemaphore     threading.BoundedSemaphore
Condition             threading.Condition
Barrier             threading.Barrier
Pool                 pool.Pool

示例:

from multiprocessing import Manager, Process
import os


def func():
    m_dict['key'] = 'value'
    m_list.append(os.getpid())


manager = Manager()
m_dict = manager.dict()
m_list = manager.list()
p_list = []
for i in range(10):
    p = Process(target=func)
    p.start()
    p_list.append(p)
for p in p_list:
    p.join()
print(m_list)
print(m_dict)

进程锁

打印时可能会出错,加锁可以避免 示例:

from multiprocessing import Lock, Process


def foo(n, l):
    l.acquire()
    print('hello world', n)
    l.release()


lock = Lock()
for i in range(100):
    process = Process(target=foo, args=(i, lock))
    process.start()

进程池 (pool)

同一时间最多有几个进程在 CPU 上运行 示例:

from multiprocessing import Pool
import time
import os


def foo(n):
    time.sleep(1)
    print('In process', n, os.getpid())
    return n


def bar(*args):
    print('>>done: ', args, os.getpid())


pool = Pool(processes=3)
print('主进程: ', os.getpid())
for i in range(10):
    # pool.apply(func=foo, args=(i, ))
    pool.apply_async(func=foo, args=(i, ), callback=bar)
print('end')
pool.close()
pool.join()

从程序运行过程中可以看出:同一时间最多只有3个进程在运行,类似于线程中的信号量 主进程在执行 callback 函数

注意

1. pool.apply(func=foo, args=(i, )) 是串行执行 pool.apply_async(func=foo, args=(i, ), callback=bar) 是并行执行 2. callback 函数会以 target 函数返回结果为参数,在 target 函数执行结束之后执行 callback 函数是主进程调用的 3. 如果不执行 join,程序会在主进程执行完成之后直接结束,不会等待子进程执行完成 Pool.join() 必须在 Pool.close() 之后执行,否则会报错:ValueError: Pool is still running

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
3个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Wesley13 Wesley13
3年前
java线程
1.进程和线程的区别是什么?进程是执行着的应用程序,而线程是进程内部的一个执行序列。一个进程可以有多个线程。线程又叫轻量级进程。2.创建线程有几种不同方式?你喜欢哪种?为什么?有三种方式可以用来创建线程:继承Thread类实现Runnable接口应用程序可以使用Executor框架来创建线程池实现Runnabl
Wesley13 Wesley13
3年前
java多线程大汇总,线程与进程,线程调度,并发与并行,创建线程方式,线程生命周期,线程安全,线程通信,线程池
1.线程与进程进程是指一个内存中运行的应用程序,每个进程都有一个独立的内存空间线程1、是进程中的一个执行路径,共享一个内存空间,线程之间可以自由切换,并发执行.一个进程最少有一个线程2、线程实际上是在进程基础之上的进一步划分,一个进程启动之后,里面的若干执行路径又可以划分成若干个线程
Wesley13 Wesley13
3年前
4、jstack查看线程栈信息
1、介绍利用jps、top、jstack命令找到进程中耗时最大的线程,以及线程状态等等,同时最后还可以显示出死锁的线程查找:FoundoneJavaleveldeadlock即可1、jps获得进程号!(https://oscimg.oschina.net/oscnet/da00a309fa6
Wesley13 Wesley13
3年前
Java并发多线程高频面试题
并发知识不管在学习、面试还是工作过程中都非常非常重要,看完本文,相信绝对能助你一臂之力。1、线程和进程有什么区别?线程是进程的子集,一个进程可以有很多线程。每个进程都有自己的内存空间,可执行代码和唯一进程标识符(PID)。每条线程并行执行不同的任务。不同的进程使用不同的内存空间(线程自己的堆栈),而所有
Stella981 Stella981
3年前
PostgreSQL死锁进程及慢查询处理
1、死锁进程查看:SELECTFROMpg_stat_activityWHEREdatname'数据库名称'andwaitingtrue;pid进程id。2、慢查询SQL:selectdatname,pid,usename,application_name,client_addr,client
Wesley13 Wesley13
3年前
Java多线程系列(1)
本章主要内容有:1.线程进程的区别2.线程的生命周期3.Java内存模型原子性,可见性及有序性4.线程池及Java实现1.线程进程的区别线程:程序运行的最小单位进程:资源分配的最小单位一个进程可以有多个线程,多个线程共享进程里面的数据线程间通讯相对更加方便,进程间通讯需要通过IPC(
Wesley13 Wesley13
3年前
Java中多线程并发体系知识点汇总
一、多线程1、操作系统有两个容易混淆的概念,进程和线程。进程:一个计算机程序的运行实例,包含了需要执行的指令;有自己的独立地址空间,包含程序内容和数据;不同进程的地址空间是互相隔离的;进程拥有各种资源和状态信息,包括打开的文件、子进程和信号处理。线程:表示程序的执行流程,是CPU调度执行的基本单位;线程有自己的程序计数器、寄存器、堆栈和帧。同一进