首页 > 系统相关 >python - 进程与线程 -1

python - 进程与线程 -1

时间:2023-05-28 12:22:50浏览次数:42  
标签:__ Process python global print 线程 time 进程

多任务就是操作系统能同时执行多个程序,比如:看电影,聊天,查看网页。进程(process)是计算机中已经运行程序的实体,一个任务就是一个进程。

1. 使用multiprocessing模块创建进程

1.1 用Process类创建进程

在这个模块中有一个Process类代表一个进程对象:

 Process(group=None, target=None, name=None, args=(), kwargs={}, *, daemon=None)
  • group: 参数未使用,值始终为None
  • target: 表示当前进程启动时执行的可调用对象
  • name: 进程 实例的别名
  • args: 传递给target函数的参数(元组)
  • kwargs:传递给target函数的参数(字典)
  • daemon:
from multiprocessing import Process


def test(*args):
    print("我是子进程:")
    for i in args:
        print(i, end=', ')


def main():
    print("主进程开始")
    # 创建进程对象
    p = Process(target=test, args=(1, "abc", 2, 3, 4))
    # 启动子进程
    p.start()
    print("主进程结束")


if __name__ == '__main__':
    main()

输出:

主进程开始
主进程结束
我是子进程:
1, abc, 2, 3, 4, 

Process的实例方法:

方法 说明
is_alive() 判断进程实例是否还在执行(True, False)
start() 启动进程实例(创建子进程)
join([timeout]) 等待进程实例执行结束,或等待多少秒
terminate() 不管任务是否完成,立即终止
run() 如果没有给定target参数,执行start时,就执行对象中的run方法
属性
name 进程别名
pid 进程PID值
import os
from multiprocessing import Process
from time import sleep


def test(args):
    print(f"我是子进程:{os.getpid()}")
    sleep(args)
    print(f"子进程:{os.getpid()}结束")


def main():
    print("主进程开始")
    # 创建进程对象
    p1 = Process(target=test, args=(1,))
    p2 = Process(target=test, args=(3,))
    # 启动子进程
    p1.start()
    p2.start()
    print(f"p1.pid:{p1.pid}, p2.pid:{p2.pid}")
    p1.join()
    p2.join()
    print("主进程结束")


if __name__ == '__main__':
    main()

1.2 用Process子类创建进程

  • 定义子类,继承Process
  • 重写Process中的run方法
from multiprocessing import Process
from time import sleep


class SubProcess(Process):
    def __init__(self, time):
        Process.__init__(self)
        self.time = time
        
	# 重写run方法,调用父类的start()时会自动执行run()
    def run(self):
        print(f"子进程{self.name}开始执行")
        sleep(self.time)
        print(f"子进程{self.name}执行结束")


def main():
    print("主进程开始")
    p1 = SubProcess(2)
    p2 = SubProcess(1)
    p1.start()
    p2.start()
    p1.join()
    p2.join()
    print("主进程结束")

if __name__ == "__main__":
    main()

1.3 用Pool进程池创建进程

进程池可指定大小,之后添加N个任务,进程池自动管理进程的运行。

Pool类的方法:

方法 说明
apply_async( func, args=(), kwds={}, callback=None, error_callback=None) 非阻塞方式调用func,并行执行任务
apply(func, args=(), kwds={}) 阻塞方式调用func,需要等上一个进程结束才能执行下一个进程。(不并行了)
close() 关闭Pool,不再接受新的任务
terminate() 不管任务是否完成,立即终止
join() 等待全部进程完成,必须在close, terminate之后使用
import os
import random
from multiprocessing import Pool
from time import sleep


def task(time):
    print(f"进程{os.getpid()}开始执行, time:{time}")
    sleep(time)
    print(f"\t进程{os.getpid()}执行结束")


def main():
    print("主进程开始")
    p = Pool(3)
    # 添加10个任务
    for i in range(10):
        p.apply_async(func=task, args=(random.randint(1, 5),))
    p.close()
    p.join()
    print("主进程结束")


if __name__ == "__main__":
    main()

执行结果:

主进程开始
进程3704开始执行, time:3
进程10648开始执行, time:3
进程10580开始执行, time:1
	进程10580执行结束
进程10580开始执行, time:3
	进程10648执行结束
	进程3704执行结束
进程10648开始执行, time:1
进程3704开始执行, time:4
	进程10648执行结束
	进程10580执行结束
进程10648开始执行, time:5
进程10580开始执行, time:2
	进程10580执行结束
进程10580开始执行, time:3
	进程3704执行结束
进程3704开始执行, time:4
	进程10648执行结束
	进程10580执行结束
	进程3704执行结束
主进程结束

可以看出,同时执行3个进程,完成一个后,另一个进程再开始执行。好比:有三个水龙头放水,要接10盆水一样,最多三个进程同时工作。

2. 进程间通信

每个进程都有自己的地址空间,内存,数据栈及其它记录其运行状态的辅助数据。


# 全局
global_value = 100


def add(time):
    global global_value
    print(f"进程{os.getpid()}开始运行,值为:{global_value}")
    global_value += 100
    sleep(time)
    print(f"进程{os.getpid()}运行结束, 值为:{global_value}")


def sub(time):
    global global_value
    print(f"进程{os.getpid()}开始运行,值为:{global_value}")
    global_value -= 100
    sleep(time)
    print(f"进程{os.getpid()}运行结束, 值为:{global_value}")


def main():
    print("主进程开始")
    p1 = Process(target=add, args=(1,))
    p2 = Process(target=sub, args=(2,))
    p1.start()
    p2.start()
    p1.join()
    p2.join()
    global global_value
    print("global:", global_value)
    print("主进程结束")


if __name__ == "__main__":
    main()

结果:


主进程开始
进程10320开始运行,值为:100
进程10320运行结束, 值为:200
进程7300开始运行,值为:100
进程7300运行结束, 值为:0
global: 100
主进程结束

可以看出global全局变量并没有在进程之间数据共享。

2.1 通过队列实现进程间的通信

使用multiprocessing模块中的Queue实现进程之间的数据传递。

q = Queue(num)

创建一个Queue对列对象

方法 说明
q.qsize() 当前队列包含的消息数量
q.empty() 队列为空返回True
q.full() 队列满了返回True
q.get(block, timeout) 从队列中获取一条消息,然后将其从队列中移除
q.get_nowait() 队列为空(读不到数据)抛出异常
q.put(item,block,timeout) 将item写入队列,block默认为True
q.put_nowait(item) 队列满了(存不了数据)抛出异常
  • block默认为True。如果block为True,而且没有指定timeout(秒),消息队列将被阻塞,直到能读取或写入消息为止。如果设置了timeout,时间到了还没读到消息或写入消息,则抛出Queue.Empty异常
  • block为False,如果消息队列满或空,即不能写入或读取直接抛出异常。
from multiprocessing import Process, Queue
from time import sleep


def write(q: Queue):
    for i in range(10):
        message = f"{i}"
        q.put(message)
        print(f"写入消息:{message}")
    q.put("end")


def read(q: Queue):
    message = ""
    while message != "end":
        sleep(1)
        message = q.get()
        print(f"\t读取消息:{message}")


def main():
    print("主进程开始")
    q = Queue(2)
    p1 = Process(target=write, args=(q,))
    p2 = Process(target=read, args=(q,))
    p1.start()
    p2.start()
    p1.join()
    p2.join()
    print("主进程结束")

结果:

主进程开始
写入消息:0
写入消息:1
	读取消息:0
写入消息:2
	读取消息:1
写入消息:3
	读取消息:2
写入消息:4
	读取消息:3
写入消息:5
	读取消息:4
写入消息:6
	读取消息:5
写入消息:7
	读取消息:6
写入消息:8
	读取消息:7
写入消息:9
	读取消息:8
	读取消息:9
	读取消息:end
主进程结束

标签:__,Process,python,global,print,线程,time,进程
From: https://www.cnblogs.com/three-sheep/p/17438070.html

相关文章

  • 【python基础】基本数据类型-字符串类型
    1.初识字符串字符串就是一系列字符。在python中,用引号括起来文本内容的都是字符串。其语法格式为:‘文本内容’或者“文本内容”我们发现其中的引号可以是单引号,也可以是双引号。这样的灵活性可以使我们进行引号之间的嵌套。编写程序如下所示:运行结果如下所示我们可以发现......
  • 完美卸载或重装Anaconda与Python环境
      本文介绍在Windows平台下,彻底删除Anaconda环境与其自带Python版本,并进行重新安装的方法。  最近,由于原有Anaconda环境中的部分第三方库出现了冲突的情况,且基于“AnacondaPrompt(anaconda3)”也无法升级Anaconda与相关库了,因此决定将其卸载并重新安装。参考Anaconda官方网......
  • 用Python开发输入法后台(6)——怎么判断是否按了单个键
    有时候我们需要判断是否按了单个键,比如按单shift键,进行中英文切换,但是shift+字母就表示输入大写字母,那么怎么区分这两种情况呢? 我想了一个办法,按下shift时记录shift键被按下,此时如果又按下其他键,就记录其他键被按下,最后当shift抬起的时候,判断是否按了其他键,......
  • Python 中的类
    在Python中,类是一种用于创建对象的蓝图或模板。类定义了对象的属性和方法,用于描述对象的行为和状态。通过类,我们可以创建多个具有相同属性和方法的对象。下面是一个简单的Python类的示例:classPerson:def__init__(self,name,age):self.name=nameself.a......
  • 线程
    并发,并行,串行的区别并发:指的同一个时间间隔内发生,交替执行并行:两个任务同一时刻同时执行,互不干扰串行:一个任务接着一个任务执行,只能等前一个执行完毕,下一个才能执行并发的三大特性原子性:操作过程中,要么所有操作都执行,要么都不执行可见性:一个线程对于......
  • Python 标准类库-因特网数据处理之Base64数据编码
    该模块提供将二进制数据编码为可打印ASCII字符并将这种编码解码回二进制数据的功能。它为RFC3548中指定的编码提供编码和解码功能。定义了Base16、Base32和Base64算法,以及事实上的标准Ascii85和Base85编码。RFC3548编码适用于对二进制数据进行编码,以便可以安全地通过电子邮件......
  • python自学笔记
    变量类型:整型int,字符串str,浮点型float;算术运算:+、-、*、/、%、**(乘方)、//(整除);逻辑运算:not、and、or;布尔类型:True、False;比较运算:>、>=、<、<=、==、!=;变量命名规则:字母+数字+下划线、区分大小写、数字不开头、不能用空格、不能用保留字;输入input()、输出print();字符串拼接:prin......
  • python3异常处理
    1、语法错误和异常语法错误是在代码执行前可以检测的,由于不符合代码语法规范引起的异常指程序运行过程中导致的超出预期处理能力的情况常见的异常:0作为除数未定义的对象被直接使用,比如参与运算或者调用其属性和方法str类型直接和非str类型相加输入输出与系统异常等异常有两......
  • python3 \r和\n
    1、说明\n:换行符,跳到下一行\r:回车,跳到当前行的首部,\r会占据一个字符长度windows下enter是\r\n; linux/unix下是\n; mac下是\r网络协议的头部字段间隔也是\r\n2、比较分析print('abc123zzz')print('abc\n123\rzzz\n1234\r',end='')print('000')""&quo......
  • python3反射
    脚本语言系列之Python|Python反射-知乎(zhihu.com)1、基本使用hasattr(obj,name_str)判断输入的name_str字符串在对象obj中是否存在(属性或方法),存在返回True,否则返回False。getattr(obj,name_str)将按照输入的name_str字符串在对象obj中查找,如找到同名属性,则返回该......