欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Python 多任务 —— 进程

程序员文章站 2022-06-08 16:28:18
...

高级编程技巧 学习笔记

一、进程


1.1、进程与程序

  • 进程: 正在执行的代码 + 用到的资源

  • 程序: 没有执行的代码,是一个静态的 exe 文件

1.2、进程的状态

Python 多任务 —— 进程


1.3、使用进程实现多任务

        multiprocessing 模块 就是跨平台的多进程模块,提供了一个 Process 类 来代表一个进程对象,这个对象可以理解为是一个独立的进程,可以执行另外的事情。

# 创建一个进程与创建线程非常相似
# 可以分别执行 线程 与 进程 , 在任务管理器中查看一下区别

import multiprocessing
import time
import threading


def demo():
    while True:
        print("--1--")
        time.sleep(1)


def demo1():
    while True:
        print("--2--")
        time.sleep(1)


def main():
    p1 = multiprocessing.Process(target=demo)
    p2 = multiprocessing.Process(target=demo1)
    # t1 = threading.Thread(target=demo)
    # t2 = threading.Thread(target=demo1)

    p1.start()
    p2.start()
    # t1.start()
    # t2.start()


if __name__ == '__main__':
    main()

  • 线程实现多任务,是在一个代码文件里面执行

  • 进程实现多任务,相当于复制一整份代码文件来执行子进程


1.4、进程与线程之间的对比

  • 进程: 能够完成多任务,一台电脑上可以同时运行多个QQ

  • 线程: 能够完成多任务,一个QQ中的多个聊天窗口(先有进程,再有线程)

  • 根本区别: 进程是操作系统资源分配的基本单位,而线程是任务调度和执行的基本单位

Python 多任务 —— 进程



二、进程间通信 - Queue


2.1、Queue(队列)

  • 先进先出
from multiprocessing import Queue


# 创建队列  最多可以存放3条数据
q = Queue(3)


# 存数据
q.put(1)
q.put("juran")
q.put([11, 22])


# 队列大小
print(f'队列大小: {q.qsize()}')
# 判断队列是否已满
print(f'队列是否已满: {q.full()}')


# 队列已满, 堵塞
# q.put({"name": "juran"})
# 不阻塞, 直接抛出异常
# q.put_nowait({"name": "juran"})


# 取数据
print('\n取出数据: ')
print(q.get())
print(q.get())
print(q.get())
print()


# 队列没有数据, 堵塞
# print(q.get())
# 不阻塞, 直接抛出异常
# print(q.get_nowait())


# 判断队列是否为满
print(f'队列是否已满: {q.full()}')
# 判断队列是否为空
print(f'队列是否为空: {q.empty()}')

2.2、使用队列实现进程间的通信

  • 边下载边保存
import multiprocessing
import time


def download(q):
    """下载数据"""
    lis = [11, 22, 33]
    for item in lis:
        q.put(item)

    print("下载到队列完成, 开始保存...\n")


def analysis(q):
    """数据处理"""
    analysis_data = list()

    # 不知道队列大小, 取完为止
    while True:
        data = q.get()
        print(f'添加 {data}')
        analysis_data.append(data)

        # 队列为空则退出
        if q.empty():
            break

    print(f'保存完成: {analysis_data}')

def main():
    # 创建一个队列  跨进程通信的队列
    # q = multiprocessing.Queue(2)
    # 不确定下载到队列的数据个数, 可以不填数值
    q = multiprocessing.Queue()

    t1 = multiprocessing.Process(target=download, args=(q, ))
    t2 = multiprocessing.Process(target=analysis, args=(q, ))

    t1.start()
    time.sleep(1)
    t2.start()


if __name__ == '__main__':
    main()

2.3、注意还有一个队列

  • from queue import Queue (普通队列,不能实现多线程)
  • from multiprocessing import Queue (实现多线程的队列)
from queue import Queue
import multiprocessing


def demo1(q):
    q.put('a')


def demo2(q):
    data = q.get()
    print(data)
    

if __name__ == '__main__':
    # 普通的队列
    q = Queue()
    # 实现多进程的队列
    # q = multiprocessing.Queue()

    t1 = multiprocessing.Process(target=demo1, args=(q,))
    t2 = multiprocessing.Process(target=demo2, args=(q,))

    # 会报错
    t1.start()
    t2.start()
    # 要想代码跑起来, 得用 run(), 但这已经不是多线程了
    # t1.run()
    # t2.run()



三、多进程共享全局变量


  • 进程是不共享的,线程是共享的
import multiprocessing
import threading

a = 1

def demo1():
    global a
    a += 1


def demo2():
    print(a)


if __name__ == '__main__':
    # 进程
    t1 = multiprocessing.Process(target=demo1)
    t2 = multiprocessing.Process(target=demo2)
    
    # 线程
    # t1 = threading.Thread(target=demo1)
    # t2 = threading.Thread(target=demo2)

    t1.start()
    t2.start()