python基础(六)

进程和线程

进程

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

验证进程独立空间

python 复制代码
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

进程通信

python 复制代码
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的执行时间。

线程数据共享

python 复制代码
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()

对比

python 复制代码
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对象 |
| 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函数:

python 复制代码
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里返回时列表 |

相关推荐
无名之逆15 小时前
Rust 开发提效神器:lombok-macros 宏库
服务器·开发语言·前端·数据库·后端·python·rust
rainFFrain16 小时前
单例模式与线程安全
linux·运维·服务器·vscode·单例模式
GalaxyPokemon16 小时前
Muduo网络库实现 [九] - EventLoopThread模块
linux·服务器·c++
xujiangyan_17 小时前
nginx的反向代理和负载均衡
服务器·网络·nginx
GalaxyPokemon18 小时前
Muduo网络库实现 [十] - EventLoopThreadPool模块
linux·服务器·网络·c++
自由鬼18 小时前
开源虚拟化管理平台Proxmox VE部署超融合
linux·运维·服务器·开源·虚拟化·pve
孤独得猿18 小时前
Qt常用控件第一部分
服务器·开发语言·qt
不爱吃鱼的猫-19 小时前
Node.js 安装与配置全攻略:从入门到高效开发
服务器·node.js
斯普信专业组19 小时前
Ceph异地数据同步之-RBD异地同步复制(下)
linux·服务器·ceph
电星托马斯19 小时前
Linux系统CentOS 6.3安装图文详解
linux·运维·服务器·程序人生·centos