在 Linux 中实现多进程的几种方式以及利用多线程实现一个文件自动复制脚本
程序员文章站
2022-05-30 12:01:45
...
在 Linux 中实现多进程的几种方式
1.通过 os 模块中的 fork() 方法创建多进程
#!/usr/bin/env python3
import os
import time
# os 中的 fork 会复制当前进程,并在当前进程下创建一个子进程
# os.fork() 有两个返回值,一个是父进程的返回值,返回的是子进程的 ID 号
# 还有一个是子进程的返回值,返回的是 0
ret = os.fork()
if ret == 0:
# os.getpid() 返回当前进程的 ID,os.getppid() 是返回当前进程的父进程 ID
print('我是子进程:%s,我的父进程是:%s.' % (os.getpid(), os.getppid()))
for i in range(5):
print('子进程正在打印...', i)
time.sleep(0.5)
else:
print('我是父进程:%s.' % os.getpid())
for i in range(5):
print('父进程正在打印...', i)
time.sleep(0.5)
2.通过 Python 中的 multiprocessing 模块创建多进程
#!/usr/bin/env python3
import multiprocessing
import time
import os
def write():
print('当前进程 ID:%s' % os.getpid())
for i in range(5):
print('人生苦短,我用 Python')
time.sleep(1)
def listen():
print('当前进程 ID:%s' % os.getpid())
for i in range(5):
print('边写代码,边听歌')
time.sleep(1)
def main():
# multiprocessing 模块中的 Process 可以创建多个进程
# target 参数用于接收进程中运行的函数名
# 如果函数中有参数可以通过 args 传入,注意 args 接收的是一个元组
# 例如: test_process = multiprocessing.Process(target=write, args=(a1,))
w_process = multiprocessing.Process(target=write)
l_process = multiprocessing.Process(target=listen)
# 光创建一个进程是不会运行的,需要把该进程启动
# 使用 start() 方法启动进程
w_process.start()
l_process.start()
if __name__ == '__main__':
main()
3.通过进程池创建多个进程
#!/usr/bin/env python3
import multiprocessing
import os
import time
def writeData(num):
for i in range(num):
print('当前进程是: %s, 正在进行第 %d 写入...' % (os.getpid(), i+1))
time.sleep(0.5)
def main():
# 创建进程池,并指定进程个数
pool = multiprocessing.Pool(3)
# apply_async 是非阻塞接收方式 进程池接收所有的操作,尽管需要执行的任务多余进程数
# apply 是阻塞式接收方式
for i in range(10):
print('----%d----' % i)
pool.apply_async(writeData, (5,))
# 关闭进程池,停止接收任务
pool.close()
# 主进程等待子进程完成后在运行,相当与阻塞
# 如果没有就不会执行子进程,程序会直接结束
pool.join()
if __name__ == '__main__':
main()
进程间通信
独立的进程不能进程相互通信,而实际生产中常常需要多进程来完成任务,如果想要进行进程间通信,则需要通过第三方来实现,Python 可以使用队列实现.
- 简单的队列
#!/usr/bin/env python3
import multiprocessing
def main():
# 创建队列, maxsize 参数指定队列最大个数
queue = multiprocessing.Queue(maxsize=3)
# 往队列中添加数据,可以是任意类型
queue.put(1)
queue.put((1,))
queue.put({1})
# 往队列中取数据
print(queue.get())
print(queue.get())
print(queue.get())
if __name__ == '__main__':
main()
队列其他方法:
- queue.qsize() 列队中数据个数
- queue.full() 返回一个布尔类型,判断队列是否已经满了
- queue.empty 返回一个布尔类型,判断队列是否是空的
通过进程池和队列实现一个多进程文件夹复制脚本
#!/usr/bin/env python3
import os
from multiprocessing import Pool, Manager
def autoCopyFile(filename, oldFileName, newFileName, queue):
# 打开旧文件夹和新文件夹下的文件
oldFile = open(oldFileName + '/' + filename, 'rb')
newFile = open(newFileName + '/' + filename, 'wb')
all_data = oldFile.readlines()
# 写入数据
for data in all_data:
newFile.write(data)
# 将文件名放入列队,实现进程间通信
queue.put(filename)
oldFile.close()
newFile.close()
def main():
# 确认目标文件夹,并创建新文件夹
oldFileName = input('输入需要复制的文件夹:')
newFileName = oldFileName + '-[复件]'
os.mkdir(newFileName)
# 找出文件夹中的文件
fileNames = os.listdir(oldFileName)
# 创建多进程
pool = Pool(5)
# 进程池中需要使用 Manager() 中的 Queue
queue = Manager().Queue()
for filename in fileNames:
pool.apply_async(autoCopyFile, args=(filename,
oldFileName,
newFileName,
queue))
pool.close()
num = 0
count = len(fileNames)
while True:
num += 1
per = num/count
# 把列队里的数据取出来
print('<%s>文件复制完成,完成度:%0.2f%%...' % (queue.get(),
per*100))
if num == count:
break
if __name__ == '__main__':
main()