python基础篇--day18

本文深入探讨了Python中的进程和线程概念,包括进程和线程的区别,如何创建和使用进程与线程,以及进程池、阻塞式与非阻塞式的应用。此外,还介绍了进程间通信的方法和自定义进程的实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

进程

Process类
进程:一个运行的程序或代码就是一个进程,一个没有运行的代码叫程序。进程是系统进行资源分配的最小单位,进程拥有自己的内存空间,所以进程间数据不共享,开销大。

多进程适合在CPU 密集型操作(cpu 操作指令比较多,如科学计算,位数多的浮点运算) 多线程适合在IO
密集型操作(读写数据操作较多的,比如爬虫)
线程是并发,进程是并行;进程之间相互独立,是系统分配资源的最小单位,同一个进程中的所有线程共享资源。

创建进程
p = Process(target=callble,name=" “,args=’’,keargs=” ")
p.start()

os.getpid() 获得当前进程号
os.getppid() 获得父线程进程号

进程
主进程:执行时的默认进程
子进程:
全局变量:
如果是全局变量,每个进程都会拥有各自的全局变量,互不影响
阻塞主线程
子进程对象.join()
方法
   start()
   run()
    terminate()
   close()   target完成后调用close()释放资源
   is_alive()  任务完成则是False,否则True
import time
import os
from multiprocessing import Process


# print('----->top:', os.getpid())

def task1():
    global number
    for i in range(5):
        print('洗衣服:', i, os.getpid(), os.getppid())
        time.sleep(0.5)
    number -= 10
    print('洗衣服:', number)


def task2(n):
    global number
    for i in range(n):
        print('劳动最光荣,扫地中...', i, os.getpid(), os.getppid())
        time.sleep(0.5)
    number -= 8
    print('扫地:', number)


number = 100
if __name__ == '__main__':
    print('main:--->start', os.getpid())
    p1 = Process(target=task1)
    p2 = Process(target=task2, args=(6,))

    p1.start()
    p2.start()

    # join() 加入   阻塞主进程后面的代码不执行
    p1.join()
    p2.join()

    print('main:--->end', os.getpid())
    print('main中的number是:', number)

进程池

Pool

阻塞式

apply

import os
import time
from multiprocessing import Pool


def task1():
    for i in range(5):
        print('洗衣服:',i, os.getpid(), os.getppid())
        time.sleep(0.5)
        # return '我是进程:' + str(os.getpid())


if __name__ == '__main__':
    pool = Pool(4)
    #
    for i in range(10):
        pool.apply(task1) # 阻塞式: 进程池中一个任务完成之后才能做下一个任务
        print('------------------------->',i)

    # 添加任务结束
    pool.close()
    # 阻塞主进程
    pool.join()

    print('main over')


非阻塞式

apply_async

import os
import time
from multiprocessing import Pool


def task1():
    print('洗衣服:', os.getpid(), os.getppid())
    time.sleep(0.5)
    return '我是进程:' + str(os.getpid())
    # response = requests.get(url)
    # return response.content


def callback(msg):
    print('{}洗衣服任务完成!'.format(msg))
    # 保存下载的文件到本地


if __name__ == '__main__':
    pool = Pool(4)
    # 非阻塞式
    for i in range(10):
        pool.apply_async(task1, callback=callback)

    # 添加任务结束
    pool.close()
    # 阻塞主进程
    pool.join()

    print('main over')

进程间的通信

Queue

put() 入队
get() 出队

full() 判断是否为满,满了则返回True
empty() 判断是否为空,若为空则返回True
qsize() 获取长度

'''
进程间通信与信号量
队列:
    FIFO

    put() : 队列中存放,如果满了则阻塞
    get() : 从队列中取值,如果空了则阻塞

'''

from multiprocessing import Process, Queue

queue = Queue(3)

queue.put('馒头1')
queue.put('馒头2')
queue.put('馒头3')
print(queue.full())  # 判断是否满了
print(queue)
print(queue.qsize())

try:
    queue.put('馒头4', timeout=3)
    queue.put('馒头5', timeout=3)
except:
    print('存放馒头失败')

while True:
    try:
        print(queue.get(timeout=1))
    except:
        print('队列为空,取不出东西')
        break


def download(url, queue):
    pass


def save_file(queue):
    pass


if __name__ == '__main__':

    q1 = Queue(2)
    p1 = Process(target=download, args=(url, q1))
    p2 = Process(target=save_file, args=(q1,))

    p1.start()
    p2.start()

    p1.join()
    p2.join()

自定义进程

'''
 p = Process(target=func,name='',args=(),kwargs={})
 自定义进程
'''
import os
import time

import requests
from multiprocessing import Process, Queue


class DownloadProcess(Process):
    def __init__(self, urls, queue):
        Process.__init__(self)
        self.urls = urls
        self.queue = queue

    # 重写父类的run方法
    def run(self):
        for image_url in self.urls:
            filename = os.path.split(image_url)[1]
            response = requests.get(image_url)
            image_data = response.content
            self.queue.put(image_data)
            self.queue.get()
            print('下载{}完毕'.format(filename))
        self.queue.close()


if __name__ == '__main__':
    q1 = Queue(2)
    images = [
        'https://gss0.bdstatic.com/94o3dSag_xI4khGkpoWK1HF6hhy/baike/c0%3Dbaike80%2C5%2C5%2C80%2C26/sign=7bf3ea52d40735fa85fd46ebff3864d6/8644ebf81a4c510f0912aa536059252dd52aa5a1.jpg',
        'https://gss1.bdstatic.com/9vo3dSag_xI4khGkpoWK1HF6hhy/baike/c0%3Dbaike92%2C5%2C5%2C92%2C30/sign=aa62e3280fb30f242197e451a9fcba26/eaf81a4c510fd9f906c11d20252dd42a2934a4a1.jpg'
    ]
    dlprocess = DownloadProcess(images, q1)

    dlprocess.start()

    for i in range(5):
        if dlprocess.is_alive():
            print('进程是活跃的:', i)
        else:
            print('进程结束了')
            dlprocess.close()
            break
        time.sleep(0.5)

线程

线程:调度执行的最小单位,也叫执行路径,不能独立存在,依赖进程的存在而存在,一个进程至少有一个线程,叫主线程,多个线程共享内存(数据共享和全局变量),因此提升程序的运行效率。

创建线程
t1 = Thread(target=函数,name=线程名)

自定义线程

import time
from threading import Thread


class MyThread(Thread):
    def __init__(self, name):
        Thread.__init__(self)
        self.name = name

    def run(self):
        for i in range(5):
            print('{}正在打印:{}'.format(self.name, i))
            time.sleep(0.1)


if __name__ == '__main__':
    t1 = MyThread('小明')
    t2 = MyThread('小花')
    t3 = MyThread('ergou')

    t1.start()
    t2.start()
    t3.start()

GIL全局变量锁

GIL是什么呢?仍然用篮球比赛的例子来帮助理解:把篮球场看作是CPU,一场篮球比赛看作是一个线程,
如果只有一个篮球场,多场比赛要排队进行,就是一个简单的单核多线程的程序;如果有多块篮球场,
多场比赛同时进行,就是一个简单的多核多线程的程序。然而python有着特别的规定:
每场比赛必须要在裁判的监督之下才允许进行,而裁判只有一个。这样不管你有几块篮球场,
同一时间只允许有一个场地进行比赛,其它场地都将被闲置,其它比赛都只能等待。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一只敲代码的大脸猫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值