1.内存管理
垃圾回收机制 :
(1) 以引用计数为主, 分代收集为辅
ps: 引用计数的缺陷是循环引用的问题
(2) 如果一个对象的引用数为0, Python虚拟机就会回收这个对象的内存
垃圾回收 :
(1) 满足特定条件, 自动启动垃圾回收
(2) 当Python运行时, 会记录其中分配对象和取消分配对象的次数
(3) 当两者的差值高于某个阈值时, 垃圾回收才会启动
(4) 查看阈值: gc.get_threshold()
分代回收 :
(1) Python将所有对象分为0、1、2 三代
(2) 所有的新建对象都是0代对象
(3) 当某一代对象经历过垃圾回收, 依然存活, 那么它就被归入下一代对象
引用计数 :
(1) 每个对象都存有指向该对象的引用总数
(2) 查看某个对象的引用计数:
sys.getrefcount()
(3) 可以用del关键字删除某个引用
2.Python多线程
1-进程 :
(1) 是一个执行中的程序
(2) 每个进程都拥有自己的地址空间、内存、数据栈以及其他用于跟踪执行的辅助数据
(3) 操作系统管理其上所有进程的执行, 并为这些进程合理地分配时间
(4) 进程也可通过派生(fork 或 spawn)新的进程来执行任务
实现一个进程 :
(1) 使用multiprocessing实现多进程代码
(2) 用multiprocessing.Process创建进程
(3) start() 启动进程、join() 挂起进程
(4) os.getpid() 获得进程ID
进程之间的通信 :
通过Queue、Pipes等实现进程之间的通信
例:
import time
import random
from multiprocessing import Process, Queue, current_process
class WriteProcess(Process):
""" 要写的内容 """
def __init__(self, q, *args, **kwargs):
self.q = q
super().__init__(*args, **kwargs)
def run(self):
""" 实现进程的业务逻辑 """
# 要写的内容
ls = [
"第1行内容",
"第2行内容",
"第3行内容"
]
for line in ls:
print('写入内容: {0}-{1}'.format(line, current_process().name))
self.q.put(line)
# 每写入一次,休息1-5秒
time.sleep(random.randint(1, 5))
class ReadProcess(Process):
""" 读取内容进程 """
def __init__(self, q, *args, **kwargs):
self.q = q
super().__init__(*args, **kwargs)
def run(self):
while True:
content = self.q.get()
print('读取到的内容: {0}-{1}'.format(content, current_process().name))
if __name__ == '__main__':
# 通过Queue共享数据
q = Queue()
t_write = WriteProcess(q)
t_write.start()
# 读取进程
t_read = ReadProcess(q)
t_read.start()
t_write.join()
# 因为读的进程是死循环, 所以需要强行终止
t_read.terminate()
输出:
写入内容: 第1行内容-WriteProcess-1
读取到的内容: 第1行内容-ReadProcess-2
写入内容: 第2行内容-WriteProcess-1
读取到的内容: 第2行内容-ReadProcess-2
写入内容: 第3行内容-WriteProcess-1
读取到的内容: 第3行内容-ReadProcess-2
使用进程池优化:
import random
import time
from multiprocessing import current_process
from multiprocessing.pool import Pool
def run(file_name, num):
""" 往文件中写入数据 """
# 当前的进程
now_process = current_process()
# 写入的内容
with open(file_name, 'a+', encoding='utf-8') as f:
content = '{0} - {1} - {2}'.format(
now_process.name,
now_process.pid,
num
)
f.write(content)
f.write('\n')
# 写完随机休息1-3秒
time.sleep(random.randint(1, 3))
print(content)
return 'ok'
if __name__ == '__main__':
file_name = 'test_pool.txt'
# 进程池
pool = Pool(2)
rest_list = []
for i in range(20):
# 同步添加任务
# rest = pool.apply(run, args=(file_name, i))
# 异步添加任务
rest = pool.apply_async(run, args=(file_name, i))
rest_list.append(rest)
print('{0} --- {1}'.format(i, rest))
# 关闭池子
pool.close()
pool.join()
# 查看异步执行的结果
print(rest_list[0].get())
输出结果:
0 --- <multiprocessing.pool.ApplyResult object at 0x0000017147352A20>
1 --- <multiprocessing.pool.ApplyResult object at 0x0000017147352B00>
2 --- <multiprocessing.pool.ApplyResult object at 0x0000017147352B70>
3 --- <multiprocessing.pool.ApplyResult object at 0x0000017147352C88>
4 --- <multiprocessing.pool.ApplyResult object at 0x0000017147352D30>
5 --- <multiprocessing.pool.ApplyResult object at 0x0000017147352DD8>
6 --- <multiprocessing.pool.ApplyResult object at 0x0000017147352E80>
7 --- <multiprocessing.pool.ApplyResult object at 0x0000017147352F28>
8 --- <multiprocessing.pool.ApplyResult object at 0x0000017147352FD0>
9 --- <multiprocessing.pool.ApplyResult object at 0x0000017147352BA8>
10 --- <multiprocessing.pool.ApplyResult object at 0x000001714736A128>
11 --- <multiprocessing.pool.ApplyResult object at 0x000001714736A198>
12 --- <multiprocessing.pool.ApplyResult object at 0x000001714736A278>
13 --- <multiprocessing.pool.ApplyResult object at 0x000001714736A320>
14 --- <multiprocessing.pool.ApplyResult object at 0x000001714736A400>
15 --- <multiprocessing.pool.ApplyResult object at 0x000001714736A4A8>
16 --- <multiprocessing.pool.ApplyResult object at 0x000001714736A550>
17 --- <multiprocessing.pool.ApplyResult object at 0x000001714736A5F8>
18 --- <multiprocessing.pool.ApplyResult object at 0x000001714736A6A0>
19 --- <multiprocessing.pool.ApplyResult object at 0x000001714736A748>
SpawnPoolWorker-1 - 3500 - 0
SpawnPoolWorker-1 - 3500 - 2
SpawnPoolWorker-2 - 7676 - 1
SpawnPoolWorker-2 - 7676 - 4
SpawnPoolWorker-1 - 3500 - 3
SpawnPoolWorker-2 - 7676 - 5
SpawnPoolWorker-1 - 3500 - 6
SpawnPoolWorker-1 - 3500 - 8
SpawnPoolWorker-2 - 7676 - 7
SpawnPoolWorker-1 - 3500 - 9
SpawnPoolWorker-2 - 7676 - 10
SpawnPoolWorker-1 - 3500 - 11
SpawnPoolWorker-2 - 7676 - 12
SpawnPoolWorker-1 - 3500 - 13
SpawnPoolWorker-1 - 3500 - 15
SpawnPoolWorker-2 - 7676 - 14
SpawnPoolWorker-1 - 3500 - 16
SpawnPoolWorker-1 - 3500 - 18
SpawnPoolWorker-2 - 7676 - 17
SpawnPoolWorker-1 - 3500 - 19
ok
2-线程
(1) 在同一个进程下执行, 并共享相同的上下文
(2) 一个进程中的各个线程与主线程共享同一片数据空间
(3) 线程包括开始、执行顺序和结束3个部分
(4) 它可以被抢占(中断)和临时挂起(睡眠)——让步
(5) 一般是以并发方式执行
PS: 并发
1. 不等同于并行。并行只是并发问题的可能方法之一
2. 是一种属性 : 程序、算法或问题的属性
3. 如果两个事件互不影响, 则两个事件是并发的
实现一个线程 :
(1) 用threading模块代替thread模块
(2) 用threading.Thread创建线程
(3) strat()启动线程
(4) join()挂起线程
1 threading模块的对象

2 thread对象数据属性

PS: 守护线程: 明面上看不到,在后台跑的线程
3 thread对象方法

3-协程
(1) 协程就是协同多任务
(2) 协程在一个进程或是一个线程中执行
(3) 不需要锁机制
(4) 对多核CPU的利用——多进程+协程
协程的实现:
使用 async 和 await 关键字实现
async 关键字 :
(1) 定义特殊函数
async def async_f():
pass
(2) 当被调用时, 不执行里面的代码, 而是返回一个协程对象
(3) 在事件循环中调度其执行前, 协程对象不执行任何操作
PS: asyncio模块:
get_event_loop() 获得事件循环队列, run_until_complete() 注册任务到队列
在事件循环中调度其执行前, 协程对象不执行任何操作 (asyncio模块用于事件循环)
await 关键字 :
(1) 等待协程完成
(2) 当遇到阻塞调用的函数的时候, 使用await方法将协程的控制权让出, 以便loop调用其他的协程
例:
import asyncio
async def do_sth(x):
""" 定义协程函数 """
print('等待中:{0}'.format(x))
# 等待 x 秒
await asyncio.sleep(5)
# 判断是否为协程函数
print(asyncio.iscoroutinefunction(do_sth))
coroutine = do_sth(5)
# 事件的循环队列
loop = asyncio.get_event_loop()
# 注册任务
task = loop.create_task(coroutine)
print(task)
# 等待协程任务执行结束
loop.run_until_complete(task)
print(task)
输出:
True
<Task pending coro=<do_sth() running at E:/PyCharmWP/test_xc1.py:4>>
等待中:5
<Task finished coro=<do_sth() done, defined at E:/PyCharmWP/test_xc1.py:4> result=None>
协程之间的数据通信
例:
import asyncio
import random
async def add(store, name):
""" 写入数据到队列 """
for i in range(5):
# 往队列中添加数字
num = '{0}-{1}'.format(name, i)
await store.put(i)
await asyncio.sleep(random.randint(1, 3))
print('{2} add one...{0},size:{1}'.format(
num, store.qsize(),name
))
async def reduce(store):
""" 从队列中删除数据 """
for i in range(10):
rest = await store.get()
print('reduce one...{0}, size:{1}'.format(rest, store.qsize()))
if __name__ == '__main__':
# 准备一个队列
store = asyncio.Queue(maxsize=5)
a1 = add(store, 'a1')
a2 = add(store, 'a2')
r1 = reduce(store)
# 添加到事件队列
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.gather(a1, a2, r1))
loop.close()
这篇博客探讨了Python的内存管理机制,包括垃圾回收的引用计数和分代收集,以及如何查看引用计数。同时,文章详细介绍了Python的多线程,包括进程的概念、创建与通信,线程的并发执行以及协程的协同多任务特性,最后展示了如何在Python中实现协程和数据通信。

643

被折叠的 条评论
为什么被折叠?



