版本一:使用shutil进行拷贝

 # -*- coding: utf-8 -*-
# @author: Tele
# @Time : 2019/04/02 下午 3:09
# 待改进:
# 1.拷贝逻辑使用原生的io
# 2.针对大文件在进程内部实现多线程方式进行拷贝 import time
import re
import os
import shutil
import multiprocessing # 遍历文件夹
def walk_file(file):
file_list = list()
for root, dirs, files in os.walk(file):
# 遍历文件
for f in files:
file_list.append(f)
return file_list # 计算文件数量
def get_file_count(dir):
return len(walk_file(dir)) def copy(src, target, queue):
target_number = 1
if os.path.isdir(src):
target_number = get_file_count(src)
shutil.copytree(src, target)
else:
shutil.copyfile(src, target)
# 将拷贝完成的文件数量放入队列中
queue.put(target_number) def copy_dir(src, desc):
total_number = get_file_count(src)
# 分隔符检测
src = check_separator(src)
desc = check_separator(desc)
# print("src:",src)
# print("desc:",desc) file_dir_list = [src + "/" + i for i in os.listdir(src)]
if os.path.exists(desc):
shutil.rmtree(desc)
pool = multiprocessing.Pool(3) # 创建队列
queue = multiprocessing.Manager().Queue() # 一个文件/目录开启一个进程去拷贝
for f_name in file_dir_list:
target = desc + "/" + f_name[index_list("/", f_name)[1] + 1:]
# print(target)
# 创建target目录
parent_path = os.path.split(target)[0]
if not os.path.exists(parent_path):
os.makedirs(parent_path)
pool.apply_async(copy, args=(f_name, target, queue,)) start = time.time()
pool.close()
# pool.join()
count = 0
while True:
count += queue.get()
# 格式化输出时两个%输出一个%,不换行,每次定位到行首,实现覆盖
print("\r拷贝进度为 %.2f %%" % (count * 100 / total_number), end="")
if count >= total_number:
break
end = time.time()
print()
print("耗时-----", (end - start), "s") # 查找指定字符出现的全部索引位置
def index_list(c, s):
return [i.start() for i in re.finditer(c, s)] # 检测目录结尾是否有 "/"
def check_separator(path):
if path.rindex("/") == len(path) - 1:
return path[0:path.rindex("/")]
return path def main():
copy_dir("f:/ftp_mypc/", "e:/ftp_mypc/") if __name__ == '__main__':
main()

这样做仍然有些小问题,对于大文件可以在进程内部采用多线程的方式,可以看到使用shutil进行拷贝时我们没有办法实现字节切割,于是有了下面的版本二

版本二:

 # -*- coding: utf-8 -*-
# @author: Tele
# @Time : 2019/04/02 下午 3:09
# 使用多进程拷贝文件夹,对于大文件进程内部又使用了多线程进行拷贝
# 使用进程池实现多进程时,使用的消息队列要使用multiprocessing.Manager().Queue()创建 import time
import re
import os
import shutil
import multiprocessing
import math
from concurrent.futures import ThreadPoolExecutor, wait # 设置单个文件的最大值:209715200 200M
MAX_SINGLE_FILE_SIZE = 209715200
mutex = multiprocessing.Lock()
executor = ThreadPoolExecutor(max_workers=3) # 遍历文件夹
def walk_file(file):
file_list = list()
for root, dirs, files in os.walk(file):
# 遍历文件
for f in files:
file_list.append(f) # 空文件夹处理
for d in dirs:
if len(os.listdir(os.path.join(root, d))) == 0:
file_list.append(d)
return file_list # 计算文件数量
def get_file_count(dir):
return len(walk_file(dir)) def copy(src, target, queue):
target_number = 1
buffer = 1024
# 文件夹
if os.path.isdir(src):
target_number = get_file_count(src)
for root, dirs, files in os.walk(src):
# 遍历文件
for f in files:
drive = os.path.splitdrive(target)[0]
target = drive + os.path.splitdrive(os.path.join(root, f))[1]
copy_single_file(buffer, os.path.join(root, f), target)
# 空文件夹
for d in dirs:
drive = os.path.splitdrive(target)[0]
target = drive + os.path.splitdrive(os.path.join(root, d))[1]
# 检查文件的层级目录
if not os.path.exists(target):
os.makedirs(target)
else:
copy_single_file(buffer, src, target)
# 将拷贝完成的文件数量放入队列中
queue.put(target_number) # 拷贝单文件
def copy_single_file(buffer, src, target):
file_size = os.path.getsize(src)
rs = open(src, "rb") # 检查文件的层级目录
parent_path = os.path.split(target)[0]
if not os.path.exists(parent_path):
os.makedirs(parent_path) ws = open(target, "wb")
# 小文件直接读写
if file_size <= MAX_SINGLE_FILE_SIZE:
while True:
content = rs.read(buffer)
ws.write(content)
if len(content) == 0:
break
ws.flush()
else:
# 设置每个线程拷贝的字节数 50M
PER_THREAD_SIZE = 52428800
# 构造参数并执行
task_list = list()
for i in range(math.ceil(file_size / PER_THREAD_SIZE)):
byte_size = PER_THREAD_SIZE
# 最后一个线程拷贝的字节数应该是取模
if i == math.ceil(file_size / PER_THREAD_SIZE) - 1:
byte_size = file_size % PER_THREAD_SIZE
start = i * PER_THREAD_SIZE + i
t = executor.submit(copy_file_thread, start, byte_size, rs, ws)
task_list.append(t)
wait(task_list)
if rs:
rs.close()
if ws:
ws.close() # 多线程拷贝
def copy_file_thread(start, byte_size, rs, ws):
mutex.acquire()
buffer = 1024
count = 0
rs.seek(start)
ws.seek(start)
while True:
if count + buffer <= byte_size:
content = rs.read(buffer)
count += len(content)
write(content, ws)
else:
content = rs.read(byte_size % buffer)
count += len(content)
write(content, ws)
break
# global total_count
# total_count += byte_size
# print("\r拷贝进度为%.2f %%" % (total_count * 100 / file_size), end="")
mutex.release() def write(content, ws):
ws.write(content)
ws.flush() def copy_dir(src, desc):
# 获得待拷贝的文件总数(含空文件夹)
total_number = get_file_count(src)
# 分隔符检测
src = check_separator(src)
desc = check_separator(desc)
# print("src:",src)
# print("desc:",desc) file_dir_list = [src + "/" + i for i in os.listdir(src)]
if os.path.exists(desc):
shutil.rmtree(desc) # 进程池
pool = multiprocessing.Pool(3) # 创建队列
queue = multiprocessing.Manager().Queue() # 一个文件/目录开启一个进程去拷贝
for f_name in file_dir_list:
target = os.path.splitdrive(desc)[0] + "/" + os.path.splitdrive(f_name)[1]
# target = desc + "/" + f_name[index_list("/", f_name)[1] + 1:]
# print(target)
# 创建target目录
parent_path = os.path.split(target)[0]
if not os.path.exists(parent_path):
os.makedirs(parent_path)
pool.apply_async(copy, args=(f_name, target, queue)) start = time.time()
pool.close()
# pool.join()
count = 0
while True:
count += queue.get()
# 格式化输出时两个%输出一个%,不换行,每次定位到行首,实现覆盖
print("\r当前进度为 %.2f %%" % (count * 100 / total_number), end="")
if count >= total_number:
break executor.shutdown()
end = time.time()
print()
print("耗时-----", (end - start), "s") # 查找指定字符出现的全部索引位置
def index_list(c, s):
return [i.start() for i in re.finditer(c, s)] # 检测目录结尾是否有 "/"
def check_separator(path):
if path.rindex("/") == len(path) - 1:
return path[0:path.rindex("/")]
return path def main():
copy_dir("f:/ftp_mypc/", "e:/ftp_mypc/") if __name__ == '__main__':
main()

python 多进程与多线程配合拷贝文件目录的更多相关文章

  1. python多进程与多线程编程

    进程(process)和线程(thread)是非常抽象的概念.多线程与多进程编程对于代码的并发执行,提升代码运行效率和缩短运行时间至关重要.下面介绍一下python的multiprocess和thre ...

  2. Python多进程与多线程编程及GIL详解

    介绍如何使用python的multiprocess和threading模块进行多线程和多进程编程. Python的多进程编程与multiprocess模块 python的多进程编程主要依靠multip ...

  3. Python多进程和多线程是鸡肋嘛?【转】

    GIL是什么 Python的代码执行由 Python虚拟机(也叫解释器主循环,CPython版本)来控制,Python在设计之初就考虑到在解释器的主循环中,同时只有一个线程在运行.即每个CPU在任意时 ...

  4. python 多进程和多线程的区别

    了解线程和进程 进程 程序:磁盘上的可执行二进制文件,并无运行状态. 进程:就是一个正在运行的任务实例(存活在内存里). 获取当前电脑的CPU核心数: pip install psutil >& ...

  5. python多进程和多线程

    多任务才有多进程和线程: 线程是最小的执行单元,而进程由至少一个线程组成.如何调度进程和线程,完全由操作系统决定,程序自己不能决定什么时候执行,执行多长时间. 多进程和多线程的程序涉及到同步.数据共享 ...

  6. Python多进程vs多线程

    多任务的两种方式:多进程和多线程. 如果用多进程实现Master-Worker,主进程就是Master,其他进程就是Worker. 如果用多线程实现Master-Worker,主线程就是Master, ...

  7. 【转】【Python】Python多进程与多线程

    1.1 multiprocessing multiprocessing是多进程模块,多进程提供了任务并发性,能充分利用多核处理器.避免了GIL(全局解释锁)对资源的影响. 有以下常用类: 类 描述 P ...

  8. Python 多进程、多线程效率比较

    Python 界有条不成文的准则: 计算密集型任务适合多进程,IO 密集型任务适合多线程.本篇来作个比较. 通常来说多线程相对于多进程有优势,因为创建一个进程开销比较大,然而因为在 python 中有 ...

  9. python 多进程,多线程,协程

    在我们实际编码中,会遇到一些并行的任务,因为单个任务无法最大限度的使用计算机资源.使用并行任务,可以提高代码效率,最大限度的发挥计算机的性能.python实现并行任务可以有多进程,多线程,协程等方式. ...

随机推荐

  1. C#中数组与ArrayList的简单使用

    1. 多维数组 2. 锯齿数组 3. 数组的常用操作 4. ArrayList 1. 多维数组 多维数组:行数和列数在定义时已确定 string[,] arr = new string[2, 3]; ...

  2. ASP.NET MVC案例教程(基于ASP.NET MVC beta)——第一篇:准备工作

    摘要      本文将简要介绍这个文章系列的目的.形式及大体内容.并且完成开始学习这个系列前所必要的准备工作. 前言      ASP.NET MVC作为微软官方的MVC解决方案,推出有一段时间了.可 ...

  3. GO语言学习(二十)Go 语言递归函数

    Go 语言递归函数 递归,就是在运行的过程中调用自己. 语法格式如下: func recursion() { recursion() /* 函数调用自身 */ } func main() { recu ...

  4. BAT面试题 - 找一个无序实数数组中的最大差值

    题目描写叙述: 一个无序的实数数组a[i].要求求里面大小相邻的实数的差的最大值.比方 double a[]={1,5,4,0.2,100} 这个无序的数组,相邻的数的最大差值为100-5=95. 题 ...

  5. 微信支付v2开发(3) JS API支付

    本文介绍如何使用JS API支付接口完成微信支付. 一.JS API支付接口(getBrandWCPayRequest) 微信JS API只能在微信内置浏览器中使用,其他浏览器调用无效.微信提供get ...

  6. web服务器软件(Nginx,Apache,IIS,Lighttpd)介绍

    Nginx是一款轻量级的Web 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,并在一个BSD-like 协议下发行.其特点是占有内存少,并发能力强,事实上nginx的并发能力确实在 ...

  7. 【例题 6-12 UVA - 572 】Oil Deposits

    [链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] dfs.. [代码] #include <bits/stdc++.h> using namespace std; con ...

  8. 【零基础入门学习Python笔记012】一个打了激素的数组3

    列表的一些经常使用操作符 比較操作符 逻辑操作符 连接操作符 反复操作符 成员关系操作符 +表示两个连接.*表示复制. list中"+"两边的类型必须一致. 演示样例: water ...

  9. BP神经网络公式推导及实现(MNIST)

    BP神经网络的基础介绍见:http://blog.csdn.net/fengbingchun/article/details/50274471,这里主要以公式推导为主. BP神经网络又称为误差反向传播 ...

  10. linux安装anaconda

    打开网址:https://repo.continuum.io/archive/ 下载对应版本: 然后把下载的文件放到linux系统上 在终端执行: bash Anaconda3-5.1.0-Linux ...