学习Python的日子 Python高级(6)

Python高级
进程
os.fork
1.创建子进程方式  window不支持 
2.主进程与子进程数据不共享
3.避免多次fork
Process类  跨平台方式
1. Process类  跨平台方式   from multiprocessing import Process
2. 参数: target=函数(进程要做的动作)  name=进程的名字  args=(参数1,参数2,)
3. 方法:
run() --->target中指定的函数代码 但是不会启动进程
start() ---> run() ,启动新的进程
join() ----> 让主进程让步,join(1)
is_alive ---> 是否当前进程还是活着的  
属性: name  pid 
自定义进程
步骤:
1. 创建子类继承Process
2. 重写run方法
3. 使用进程子类
案例
import os
import time
from multiprocessing import Process




# 1. 创建子类继承Process
class MyProcess(Process):


# 2. 重写run方法
def run(self):
t1=time.time()
for i in range(5):
print("i=%d,当前进程:%s,父进程:%s" % (i, self.name, os.getppid()))
time.sleep(0.01)
t2 = time.time()
print(self.name, "用时:", (t2 - t1))


# 3. 使用自定的进程子类MyProcess


if __name__ == "__main__":
# 创建进程
p = MyProcess()
p.name = "进程1"
p.start()


# 创建进程
p1 = MyProcess()
p1.name = "进程2"
p1.start()


p.join()


for n in range(5):
print("当前进程ID:%s" % (os.getpid()))
time.sleep(0.01)
进程池
1. 主进程执行任务结束,进程池中任务也结束(即使没有完成任务)
2. pool.join()  # 主进程让步
3. 回调函数: 任务执行完毕之后才会调用回调函数 
A》 任务中是否存在返回值   ----》回调函数的参数接收返回值
B》 回调函数必须存在一个参数接收返回值  def callback_func(n): pass
pool.apply_async
案例
import os
import time
from multiprocessing import Pool




# 1. 定义任务
def download(name):
print("即将下载:", name)
time.sleep(1)
print("下载 %s 100%%" % (name))
return name




# 2. 任务完成后
def callback_func(filename):
print(filename, "下载完毕!")




if __name__ == "__main__":
image_names = ["aa.jpg", "mm1.jpg", "美女.jpg", "flower.jpg"]


pool = Pool(3)


for image in image_names:
obj = pool.apply_async(download, args=(image,), callback=callback_func)
print(obj)


pool.close()


pool.join()


print("主进程: 所有图片下载完毕!")


阻塞式
阻塞式obj对象其实就是任务返回值
pool.apply
案例
import os
import time
from multiprocessing import Pool




# 1. 定义任务
def download(name):
print("即将下载:", name)
time.sleep(1)
print("下载 %s 100%%" % (name))
return name






if __name__ == "__main__":
image_names = ["aa.jpg", "mm1.jpg", "美女.jpg", "flower.jpg"]


pool = Pool(3)


for image in image_names:
obj = pool.apply(download, args=(image,))   # 阻塞式obj对象其实就是任务返回值
print("====>",obj)


# pool.close()


# pool.join()


print("主进程: 所有图片下载完毕!")
Queue队列
步骤:
1.导模块
  multiprocessing ---》Queue
2.创建队列对象
  queue=Queue(数量)
3.添加内容:
queue.put("aaa")  可以一直添加,但是满了之后就会阻塞
qu.put_nowait("hahah1")  可以一直添加,但是满了之后就会报错
queue.qsize()  获取队列中长度
4. 取内容:
queue.get() : 如果队列中没有则会阻塞,有则从队列中取出   返回值就是取出的内容
qu.get(timeout=1): 阻塞指定的时间,到时间后没有则报出异常
queue.get_nowait():有则从队列中取出 队列中没有则会报错
5. queue.empty()  返回值True,False
案例
from multiprocessing import Queue, Process
import time




# 西雅
def save(queue):
foods = ["北京烤鸭", "锅包肉", "面包", "牛奶", "麻辣烫"]
print(queue.empty())
if queue.empty():
for i in foods:
queue.put(i)
print("西雅送餐是:",i)
time.sleep(0.01)




# 玉峰
def withdraw(queue):
try:
while True:
food = queue.get(timeout=2)  # 阻塞
print("很高兴哈哈哈,吃到了:", food)
except:
print("呜呜呜呜。。。。没有吃的啦。。。")
finally:
print("送餐完毕!")




if __name__ == "__main__":
# 1. 准备队列
qu = Queue(5)


# 2.准备进场
xiya = Process(target=save, args=(qu,), name="西雅")
yufeng = Process(target=withdraw, args=(qu,), name="玉峰")


xiya.start()
yufeng.start()


xiya.join()
yufeng.join()


print("主进程打印:game over!")
进程间的通信: 都是Queue作为参数传递到任务中的
1.使用Process进程   ----》 队列: Queue() --->queue对象  ---》put  get  qsize  
2.使用的进程池  ----》队列: Manager().Queue()   --->queue对象  ---》put  get  qsize
多进程拷贝
import os
import time
from multiprocessing import Queue, Process




def save_file(old_folder, new_folder, all_files, qu):
for file in all_files:
fr = open(old_folder + "/" + file, "r")
fw = open(new_folder + "/" + file, "w")


content = fr.read()
fw.write(content)


fr.close()
fw.close()
time.sleep(0.5)
qu.put(file)




def get_content(qu):
# while True:
# file_name = qu.get(timeout=2)
# print("复制完成:", file_name)
num = 0
while num <=length:
file_name = qu.get()
num += 1
copy_range = num / length
# %s  100%%   %s  %d  %.1f
print("\rcopy的进度是:%.2f %%" % (copy_range * 100), end="")




if __name__ == "__main__":
old_folder = input("输入文件夹的名称:")
new_folder = old_folder + "-副本"


os.mkdir(new_folder)


all_files = os.listdir(old_folder)
print(all_files)
# 文件数量
length = len(all_files)


# 1.创建队列
qu = Queue(5)


# 2. 创建进程
p = Process(target=save_file, args=(old_folder, new_folder, all_files, qu))
p1 = Process(target=get_content, args=(qu,))


p.start()
p1.start()


p.join()
p1.join()


print("-" * 60)
总结
进程
并发  并行  串行
创建进程:
1. os.fork()
2. Process(target=函数,args=(aa,))  扩展: 自定义的Process
3. 进程池:pool=Pool(5) 
       A.阻塞式  pool.apply(函数,args=(aaa))
       B.非阻塞式   pool.apply_async(函数,args=(),callback=回调函数)   pool.close()   pool.join()
4. Queue: 进程间通信
A.Process  +  Queue
B.Pool  +  Manager().Queue()      
线程
from threading import Thread   导入模块中的线程Thread类
os.getpid() 两个线程获取的是相同的进程pid
t1.start()  不能启动多次,只能启动一次
自定义线程
import os
import time
from threading import Thread




# 1. 继承Thread
class MyThread(Thread):
def __init__(self, tname, args=()):
super().__init__()
self.name = tname
# print(args)
self.args = args


# 2. 重写run()
def run(self):
if len(self.args) == 0:
print("不循环!")
else:
for i in range(self.args[0]):
print(os.getpid(), self.name, "----->", i)  # os.getpid() 两个线程获取的是相同的进程pid
time.sleep(0.5)




# 创建Thread对象
if __name__ == "__main__":
t1 = MyThread("西雅", args=(1, 2))
t1.setName("小雅")
t1.start()


t2 = MyThread("西雅1")
t2.setName("小雅1")
t2.start()
多线程中全局变量在线程中共享的
from threading import Thread
import time
import os


number = 0  # 全局变量




def task(n):
global number
for i in range(10):
number += i
if n == 1:
print("---11111-->", number, i)
elif n == 2:
print("===22222===>", number, i)
time.sleep(0.5)




if __name__ == "__main__":
t1 = Thread(target=task, args=(1,))


t2 = Thread(target=task, args=(2,))


t1.start()


t2.start()
多线程中局部变量在线程中共享的
from threading import Thread
import time
import os


list1 = []  # 共享的




class Person:
pass




person = Person()  # person对象 共享 ----》内存  ----》内存中属性 共享


#


def task(n):
number = 0  # 函数中声明


for i in range(3):
number += i


if n == 1:
print("---11111-->", number, i)
elif n == 2:
print("===22222===>", number, i)
person.age = n
list1.append(number)
time.sleep(0.5)


print("n----->", list1, person.age)




if __name__ == "__main__":
t1 = Thread(target=task, args=(1,))


t2 = Thread(target=task, args=(2,))


t1.start()


t2.start()


t1.join()
t2.join()


print("---主-->",person.age)
在多线程开发中:
1. 全局变量是多个线程都共享的数据;
2. 而局部变量等是各自线程的,【类属性是共享的,实例属性是非共享的 类:自定义线程类】。各个实例对象彼此间数据也是不共享的。
共享安全问题
from threading import Thread


# 全局变量
g_num = 0




def worker1():
global g_num
for i in range(1000000):
g_num += 1
print("在worker1中g_num==", g_num)




def worker2():
global g_num
for i in range(1000000):
g_num += 1
print("在worker2中g_num==", g_num)




if __name__ == "__main__":
t1 = Thread(target=worker1)


t2 = Thread(target=worker2)


t1.start()


t2.start()


t1.join()
t2.join()


print("---主-->", g_num)
1. 多个线程共同操作一个共享数据
2. 每个线程中操作共享数据的代码可能有多行

猜你喜欢

转载自blog.csdn.net/qq_42240071/article/details/80447713
今日推荐