当前位置: 首页 > article >正文

python基础(六)

进程和线程

进程

进程就是操作系统中执行的一个程序,操作系统以进程为单位分配存储空间,每个进程都有自己的地址空间、数据栈以及其他用于跟踪进程执行的辅助数据,操作系统管理所有进程的执行,为它们合理的分配资源。创新的进程有自己独立的内存空间,因此必须通过进程间通信机制(IPC,Inter-Process Communication)来实现数据共享,具体的方式包括管道、信号、套接字、共享内存区等。

验证进程独立空间

import multiprocessing
import os
#验证父进程在创建子进程时复制了进程及其数据结构每个进程都有自己独立的内存空间 
def process_func(value):
    # 在这个函数内部,尝试修改全局变量,但是这是在不同的内存空间中
    global_var = value
    global_var += 1
    print(f"son PID {multiprocessing.current_process().pid}: global_var = {global_var}")
 
if __name__ == "__main__":
    # 主进程中的全局变量
    global_var = 0
    # 创建并启动一个子进程
    p = multiprocessing.Process(target=process_func, args=(global_var,))
    p.start()
    p.join()    # 等待子进程完成
    # 主进程中打印全局变量的值
    print(f"Main process PID: {os.getpid()}, global_var = {global_var}")
#son PID 22916: global_var = 1
#Main process PID: 70036, global_var = 0

进程通信

import multiprocessing
import os
def sub_task(queue):
    print('子进程进程号:', os.getpid())  #子进程进程号: 3xxx
    for i in range(1,5):
        queue.put(i)  #将元素放在队列的末尾‌

if __name__ == '__main__':
    print('主进程号:', os.getpid())  #主进程号: xxx
    queue = multiprocessing.Queue()
    p = multiprocessing.Process(target=sub_task, args=(queue,))
    p.start()
    counter = 0
    for i in 'ABCD':
        queue.put(i)
    p.join() #子任务已经完成
    for _ in range(8):
        print(queue.get(), end='')  #ABCD1234

线程

一个进程还可以拥有多个并发的线程,简单的说就是拥有多个可以获得CPU调度的执行单元,这就是所谓的线程。由于线程在同一个进程下,它们可以共享相同的上下文,因此相对于进程而言,线程间的信息共享和通信更加容易。当然在单核CPU系统中,真正的并发是不可能的,因为在某个时刻能够获得CPU的只有唯一的一个线程,多个线程共享了CPU的执行时间。

线程数据共享

import threading
from threading import Thread
 
# 全局变量 主线程中创建了一个全局变量,那么这个变量对于所有的其他线程来说也是可见的
g_num = 0
lock = threading.Lock() #使用了一个锁lock来确保每次只有一个线程可以修改 g_num
def thread_function():
    global g_num   #每个线程都能看到 g_num 的变化
    with lock:     #with 语句保证在执行增加操作的时候lock会被自动获取和在操作完成后自动释放
        g_num += 1
    print(f"Thread {threading.get_ident()}: g_num = {g_num}")
 
def main():
    t = Thread(target=thread_function)
    t.start()
    t1 = Thread(target=thread_function)
    t1.start()
    t.join()
    t1.join()
if __name__ == "__main__":
    main()

对比

import threading
from multiprocessing import Process
import time
lock=threading.Lock()
global_v=0
def show_fuc_without_lock():
    global global_v
    global_v+=1
    print(global_v)
def show_fuc_with_lock():
    global global_v
    global_v+=1
    print(global_v)
def show_fuc(name):
    for i in range(6):
        print(name,end=' ')
        time.sleep(1)
        print(i)

def print_fuc(name):
    for i in 'abcde':
        print(name,end=' ')
        time.sleep(1)
        print(i)

if __name__=='__main__':
    th1=threading.Thread(target=show_fuc, args=('show_fuc',))
    th2=threading.Thread(target=print_fuc,args=('print_fuc',))
    th1.start()  #多个线程完成多个任务
    th2.start()  #多个线程完成多个任务
    th1.join()
    th2.join()
    # p1=Process(target=show, args=('p_show',))
    # p2=Process(target=show1, args=('p_show1',))
    # p1.start()   #多进程的并行执行
    # p2.start() 
    # threads = [threading.Thread(target=show_fuc_lock) for _ in range(10)]
    # for t in threads:
    #     t.start()
    # 等待所有线程完成 
    # for t in threads:
    #     t.join()

pickling和unpickling

pickling将一个python对象转换为一个字节流以便将其存储到文件中或通过网络传输unpickling是将字节流重新转换回原来的python对象
import pickle
data={'A':'b','he':2,'istrue':True}
with open('test.txt','wb') as f:
    pickle.dump(data,f)
with open('test.txt','rb') as f:
    data=pickle.load(f)
import json #更安全序列化
with open('data.json','w') as f:
    json.dump(data,f)
with open('data.json','r') as f:
    data=json.load(f)

python内存管理机制

python里内存管理主要依赖于自动内存管理机制,特别是垃圾回收机制,python使用引用计数和垃圾回收相结合的方式来管理内存;每个对象的引用次数将为零时python会立即回收相关内存;python内置的垃圾回收器专门处理引用循环的问题。

python程序退出时,不一定能释放所有内存,python的垃圾回收器尝试回收不再使用的内存,但是由于一些引用循环依赖于垃圾回收发现和处理,程序退出时并不保证足够的时间处理所有循环引用;还有一些外部C库的资源管理问题,C库可能分配程序一些内存,python退出时并不负责清理这些外部库分配的内存,需要依赖这些库本身提供的清理机制否则会有内存泄漏,防止内存泄漏可以使用上下文管理器来管理资源,比如使用with open() as file确保文件操作后文件会自动关闭,尽量减少全局变量的使用及时清理不再需要的对象。

python的深拷贝与浅拷贝

浅拷贝:拷贝父对象,不会拷贝对象内部的子对象。深拷贝:拷贝父对象以及对象内部的所有子对象。在Python中,可以使用copy模块来实现浅拷贝和深拷贝。浅拷贝使用copy模块的copy函数:

import copy
 
original_list = [1, 2, [3, 4]]
shallow_copy = copy.copy(original_list)
deep_copy=copy.deepcopy(original_list)
print(original_list)  # 输出: [1, 2, [3, 4]]
print(shallow_copy)  # 输出: [1, 2, [3, 4]]
print(deep_copy)  # 输出: [1, 2, [3, 4]]
original_list[2][0]=0
print(original_list)  # 输出: [1, 2, [0, 4]]
print(shallow_copy)  # 输出: [1, 2, [0, 4]]
print(deep_copy)  # 输出: [1, 2, [3, 4]]

python3 VS python2

打印语句p2里print是语句print”hell“, p3里print变为一个函数print(”hell“)
整数除法p2里5/2=2,  p3里5/2=2.5
字符串p2里默认字符串类型是ASCII,文件编码需要显示声明coding=utf-8,p3是默认类型是Unicode,默认文件编码utf-8
内置函数变化p2里range() 返回一个列表, p3返回迭代器,你需要list(range(2))返回列表
库的改进p3对许多内置库和语法进行改进和简化,提升可读性和性能如urllib, input()函数
异常处理p2写异常except SomeException,e ; p3使用except SomeException as e
数据类型p3增加新数据类型如bytes,处理字节数据,还引进了诸如functools。pathlib
迭代器和生成器p3对迭代器和生成器进一步优化,提高了性能,如map(), filter(),zip()等在p3中返回迭代器,p2里返回时列表

 


http://www.kler.cn/a/420669.html

相关文章:

  • 蓝桥杯准备训练(lesson1,c++方向)
  • 装饰器—购物打折
  • 【Nacos01】消息队列与微服务之Nacos 介绍和架构
  • redis 快 原因 详解
  • MAUI APP开发蓝牙协议的经验分享:与跳绳设备对接
  • 第1章:CSS简介 --[CSS零基础入门]
  • 依赖注入之登录验证(Java EE 学习笔记08)
  • [JuMP.jl] 线性规划
  • 107.【C语言】数据结构之二叉树求总节点和第K层节点的个数
  • 针对Qwen-Agent框架的Function Call及ReAct的源码阅读与解析:Agent基类篇
  • 人证合一开启安全认证新时代、C#人证合一接口集成、人脸识别
  • 第一部分:基础知识 3. 数据类型 --[MySQL轻松入门教程]
  • 实战优化公司线上系统JVM:从基础到高级
  • 《Vue零基础入门教程》第十三课:条件渲染
  • PowerShell:查找并关闭打开的文件
  • Modern Effective C++ 条款二十三:理解std::move和std::forward
  • java 网络编程 详解
  • 数据结构判断两棵树是否相等
  • 九,[极客大挑战 2019]LoveSQL1
  • JavaWeb—— 构建互联网世界的 “魔法砖石” 与实战密码
  • 企业品牌曝光的新策略:短视频矩阵系统
  • 多模态抑郁估计论文研读|Multi-modal Depression Estimation Based on Sub-attentional Fusion
  • 【QNX+Android虚拟化方案】123 - 如何配置qnx侧GPIO_IRQ中断和PMIC_GPIO_IRQ中断
  • 【Android】View工作原理
  • Linux 内核系统架构
  • Kafka-Consumer源码分析