一、进程
正在运行的应用程序就是一个进程。进程是资源分配的基本单元。 每一个进程有一个GIL,在一个进程中,同时只能有一个线程执行(获取到GIL的那个线程)。 在Python中,多线程不能同时在多核CPU上执行,但是多进程可以在多核CPU上运行,多进程 充分利用了多核的资源。
1..1 进程的创建方式
方式一: 继承from multiprocessing import Process类,复写run()方法, 启动进程时,调用进程对象的start()方法。 class MyProcess(Process): def __init__(self,processName): Process.__init__(self,name=processName) def run(self): 进程运行的代码 process = MyProcess("child_process") process.start()
方式二:实例化Process对象,并指定target、args等参数,确定进程要执行的 某个函数或方法。 eg: process = Process(target=func,name="ChildProcess",args=("赵云",25,"男")) process.start() 注意:启动子进程时,需要添加 if __name__ == '__main__': freeze_support()
代码演示
import time from multiprocessing import Process, current_process, freeze_support class MyProcess(Process): def __init__(self,processName): Process.__init__(self,name=processName) def run(self): while True: # time.sleep(0.01) print(current_process().name+"正在运行...") if __name__ == '__main__': freeze_support() process = MyProcess("child_process") process.start() while True: # time.sleep(0.01) print(current_process().name + "正在运行...")
import time from multiprocessing import Process, current_process, freeze_support def func(name,age,sex): while True: time.sleep(2) print(current_process().name+"正在运行,姓名:"+name+"年龄:"+str(age)+";性别:"+sex) if __name__ == '__main__': freeze_support() process = Process(target=func,name="ChildProcess",args=("赵云",25,"男")) process.start() # process.join() while True: time.sleep(2) print(current_process().name+"正在运行...")
1.2 进程通信——通过进程队列
(from multiprocessing import Queue) queue = Queue() queue.put(传递的对象) # 在第一个进程中通过队列传递数据 data = queue.get() # 在第二个进程中接收队列里的数据
代码演示
import time from multiprocessing import Process, Queue, current_process, freeze_support class MyProcess(Process): def __init__(self,processName,q): Process.__init__(self,name=processName) self.q = q def run(self): q = self.q print(current_process().name+"准备接受数据...") data = q.get() # 接收队列里的数据 print(current_process().name,"接收到的数据是:",data) if __name__ == '__main__': freeze_support() queue = Queue() queue.put(['hello', 'world']) process = MyProcess("接收数据进程",queue) process.start() process.join() print("主进程结束...")
1.3 进程通信——通过管道Pipe通信
conn1,conn2 = Pipe() # 实例化管道对象 分别在两个进程中使用conn1和conn2,发送和接收数据 conn1.send(在第一个进程中发送的数据) data = conn2.recv() # 在第二个进程中接收数据
代码演示
from multiprocessing import Process, Pipe, freeze_support, current_process def my_function(conn): conn.send(["苹果","足球","真心英雄","电脑"]) conn.close() print(current_process().name+"发送数据成功...") if __name__ == "__main__": freeze_support() conn1,conn2 = Pipe() # 实例化管道对象 process = Process(target=my_function,args=(conn1,)) process.start() data = conn2.recv() print(current_process().name,"获取到的数据是:",data)
1.4 进程池
如果需要大量进程,手工创建进程的方式不能有效管理这些进程,此时就 需要进程池的协助。 from multiprocessing import Pool pool = Pool(processes=3) # 实例化进程池,系统自动创建规定的进程数 result = pool.apply_async(task) pool.close() pool.join() # 等待进程池中的所有进程运行完毕,当前主进程才开始执行
注意:调用join()方法之前,必须调用close()方法。
代码演示
from multiprocessing import Process, Pool, current_process, freeze_support import time def task(): print("task...") for i in range(5): print(current_process().name+"正在执行任务:"+str(i)) time.sleep(2) if __name__ == '__main__': freeze_support() pool = Pool(processes=3) # 实例化进程池,系统自动创建规定的进程数 pool.apply_async(task) pool.close() pool.join() # 等待进程池中的所有进程运行完毕,当前主进程才开始执行 # print(result.successful())
1.5 进程间共享数据
使用from multiprocessing import Value,Array value = Value("i",1) # 在第一个进程中创建Value对象,携带了整数1 value.value += 100 # 在第二个进程中,获取携带的值,并自增
array = Array("d",5) # 在第一个进程中创建Array for index in range(len(array)): # 在其他进程中修改 array[index] = 500
代码演示
from multiprocessing import Process, freeze_support, Queue,Value,Array class MyFruit: def __init__(self): self.fruits = ["香蕉"] def func(value,array): value.value += 100 # 在子进程中,获取携带的值,并自增 for index in range(len(array)): array[index] = 500 print("子进程修改完毕") if __name__ == '__main__': freeze_support() value = Value("i",1) # 在主进程中创建Value对象,携带了整数1 array = Array("d",5) print("在主进程中原来的值为:", value.value) process = Process(target=func,args=(value,array)) process.start() process.join() print("在主进程中现在的值为:",value.value) for item in array: print(item)
二、homework
代码演示
1、只读取文件夹下所有文件内容
import os path = r'C:\ywh\爬虫\爬虫第二天\crawler' gen = os.walk(path) filelist = [] for dirpath, dirnames, filenames in gen: for filename in filenames: filelist.append(os.path.join(dirpath,filename)) for filepath in filelist: with open(filepath) as f: for line in f: print(line)
2、使用多进程统计某文件目录下所有文件里的单词量
import os import time from multiprocessing import Process, current_process, freeze_support def getFileList(path): gen = os.walk(path) filelist = [] for dirpath, dirnames, filenames in gen: for filename in filenames: filelist.append(os.path.join(dirpath, filename)) print(filelist) return filelist class WordsProcess(Process): def __init__(self,processName,filelist): Process.__init__(self,name=processName) self.filelist = filelist # 接收分配给当前进程的文件路径列表 def run(self): words_count = 0 for filepath in self.filelist: with open(filepath) as f: for line in f: # 逐行遍历当前文件 wordslist = line.strip().split() # 以默认的空白字符串拆分当前行 words_count += len(wordslist) print(current_process().name+"统计的单词数量为:"+str(words_count)) if __name__ == '__main__': freeze_support() path = 'C:\ywh\爬虫\爬虫第二天\crawler' filelist = getFileList(path) size = len(filelist) # 总文件个数 print(size) first_part_count = int(size/2) # 分配给第一个进程的文件个数 word_thread1 = WordsProcess("统计侠进程",filelist[:first_part_count+1]) word_thread1.start() word_thread2 = WordsProcess("大数据进程", filelist[first_part_count+1:]) word_thread2.start()