Python3 filecmp模块测试比较文件原理解析


Posted in Python onMarch 23, 2020

1.filecmp比较文件

filecmp模块提供了一些函数和一个类来比较文件系统上的文件和目录。

1.1 示例数据

使用下面代码创建一组测试文件。

import os
def mkfile(filename, body=None):
  with open(filename, 'w') as f:
    f.write(body or filename)
  return
 
def make_example_dir(top):
  if not os.path.exists(top):
    os.mkdir(top)
  curdir = os.getcwd()
  os.chdir(top)
  os.mkdir('dir1')
  os.mkdir('dir2')
  mkfile('dir1/file_only_in_dir1')
  mkfile('dir2/file_only_in_dir2')
  os.mkdir('dir1/dir_only_in_dir1')
  os.mkdir('dir2/dir_only_in_dir2')
  os.mkdir('dir1/common_dir')
  os.mkdir('dir2/common_dir')
  mkfile('dir1/common_file', 'this file is the same')
  os.link('dir1/common_file', 'dir2/common_file')
  mkfile('dir1/contents_differ')
  mkfile('dir2/contents_differ')
  # Update the access and modification times so most of the stat
  # results will match.
  st = os.stat('dir1/contents_differ')
  os.utime('dir2/contents_differ', (st.st_atime, st.st_mtime))
  mkfile('dir1/file_in_dir1', 'This is a file in dir1')
  os.mkdir('dir2/file_in_dir1')
  os.chdir(curdir)
  return
 
if __name__ == '__main__':
  os.chdir(os.path.dirname(__file__) or os.getcwd())
  make_example_dir('example')
  make_example_dir('example/dir1/common_dir')
  make_example_dir('example/dir2/common_dir')

运行这个脚本会在axample目录下生成一个文件树。

Python3 filecmp模块测试比较文件原理解析

common_dir目录下也有同样的目录结构,以提供有意思的递归比较选择。

1.2 比较文件

cmp()用于比较文件系统上的两个文件。

import filecmp
print('common_file  :', end=' ')
print(filecmp.cmp('example/dir1/common_file',
         'example/dir2/common_file',
         shallow=True),
   end=' ')
print(filecmp.cmp('example/dir1/common_file',
         'example/dir2/common_file',
         shallow=False))
print('contents_differ:', end=' ')
print(filecmp.cmp('example/dir1/contents_differ',
         'example/dir2/contents_differ',
         shallow=True),
   end=' ')
print(filecmp.cmp('example/dir1/contents_differ',
         'example/dir2/contents_differ',
         shallow=False))
print('identical   :', end=' ')
print(filecmp.cmp('example/dir1/file_only_in_dir1',
         'example/dir1/file_only_in_dir1',
         shallow=True),
   end=' ')
print(filecmp.cmp('example/dir1/file_only_in_dir1',
         'example/dir1/file_only_in_dir1',
         shallow=False))

shallo参数告诉cmp()除了文件的元数据外,是否还要查看文件的内容。默认情况下,会使用由os.stat()得到的信息来完成一个浅比较。如果结果是一样的,则认为文件相同。因此,对于同时创建的相同大小的文件,即使他们的内容不同,也会报告为是相同的文件。当shallow为False时,则要比较文件的内容。

Python3 filecmp模块测试比较文件原理解析

如果非递归的比较两个目录中的一组文件,则可以使用cmpfiles()。参数是目录名和两个位置上要检查的我就爱你列表。传入的公共文件列表应当只包含文件名(目录会导致匹配不成功),而且这些文件在两个位置上都应当出现。下一个例子显示了构造公共列表的一种简单方法。与cmp()一样,这个比较也有一个shallow标志。

import filecmp
import os
# Determine the items that exist in both directories
d1_contents = set(os.listdir('example/dir1'))
d2_contents = set(os.listdir('example/dir2'))
common = list(d1_contents & d2_contents)
common_files = [
  f
  for f in common
  if os.path.isfile(os.path.join('example/dir1', f))
]
print('Common files:', common_files)
# Compare the directories
match, mismatch, errors = filecmp.cmpfiles(
  'example/dir1',
  'example/dir2',
  common_files,
)
print('Match    :', match)
print('Mismatch  :', mismatch)
print('Errors   :', errors)

cmpfiles()返回3个文件名列表,分别包含匹配的文件、不匹配的文件和不能比较的文件(由于权限问题或出于其他原因)。

Python3 filecmp模块测试比较文件原理解析

1.3 比较目录

前面介绍的函数适合完成相对简单的比较。对于大目录树的递归比较或者更完整的分析,dircmp类很更有用。在最简单的用例中,report()会打印比较两个目录的报告。

import filecmp
dc = filecmp.dircmp('example/dir1', 'example/dir2')
dc.report()

输出是一个纯文本报告,显示的结果只包括给定目录的内容,而不会递归比较其子目录。在这里,认为文件not_the_same是相同的,因为这里没有比较内容。无法让dircmp像cmp()那样比较文件的内容。

Python3 filecmp模块测试比较文件原理解析

为了更多的细节,也为了完成一个递归比较,可以使用report_full_closure()。

import filecmp
dc = filecmp.dircmp('example/dir1', 'example/dir2')
dc.report_full_closure()

输出将包括所有同级子目录的比较。

Python3 filecmp模块测试比较文件原理解析

1.4 在程序中使用差异

除了生成打印报告,dircmp还能计算文件列表,可以在程序中直接使用。以下各个属性只在请求时才计算,所以对于未用的数据,创建dircmp实例不会带来开销。

import filecmp
import pprint
dc = filecmp.dircmp('example/dir1', 'example/dir2')
print('Left:')
pprint.pprint(dc.left_list)
print('\nRight:')
pprint.pprint(dc.right_list)

所比较目录中包含的文件和子目录分别列在left_list和right_list中。

Python3 filecmp模块测试比较文件原理解析

可以向构造函数传入一个要忽略的名字列表(该列表中指定的名字将被忽略)来对输入进行过滤。默认的,RCS、CVS和tags等名字会被忽略。

import filecmp
import pprint
dc = filecmp.dircmp('example/dir1', 'example/dir2',
          ignore=['common_file'])
print('Left:')
pprint.pprint(dc.left_list)
print('\nRight:')
pprint.pprint(dc.right_list)

在这里,将common_file从要比较的文件列表中去除。

Python3 filecmp模块测试比较文件原理解析

两个输入目录中共有的文件名会保存在common内,各目录独有的文件会列在left_only和right_only中。

import filecmp
import pprint
dc = filecmp.dircmp('example/dir1', 'example/dir2')
print('Common:')
pprint.pprint(dc.common)
print('\nLeft:')
pprint.pprint(dc.left_only)
print('\nRight:')
pprint.pprint(dc.right_only)

"左"目录是dircmp()的第一个参数,"右"目录是第二个参数。

Python3 filecmp模块测试比较文件原理解析

公共成员可以被进一步分解为文件、目录和“有趣”元素(两个目录中类型不同的内容,或者os.stat()指出的有错误的地方)。

import filecmp
import pprint
dc = filecmp.dircmp('example/dir1', 'example/dir2')
print('Common:')
pprint.pprint(dc.common)
print('\nDirectories:')
pprint.pprint(dc.common_dirs)
print('\nFiles:')
pprint.pprint(dc.common_files)
print('\nFunny:')
pprint.pprint(dc.common_funny)

在示例数据中,file_in_dir1元素在一个目录中是一个文件,而在另一个目录中是一个子目录,所以它会出现在“有趣”列表中。

Python3 filecmp模块测试比较文件原理解析

文件之间的差别也可以做类似的划分。

import filecmp
dc = filecmp.dircmp('example/dir1', 'example/dir2')
print('Same   :', dc.same_files)
print('Different :', dc.diff_files)
print('Funny   :', dc.funny_files)

文件not_the_same通过os.stat()比较,并且不检查内容,所以它包含在same_files列表中。

Python3 filecmp模块测试比较文件原理解析

最后一点,子目录也会被保存,以便容易地完成递归比较。

import filecmp
dc = filecmp.dircmp('example/dir1', 'example/dir2')
print('Subdirectories:')
print(dc.subdirs)

属性subdirs是一个字典,它将目录名映射到新的dircmp对象。

Python3 filecmp模块测试比较文件原理解析

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python中实现字符串类型与字典类型相互转换的方法
Aug 18 Python
Python的subprocess模块总结
Nov 07 Python
Python基于回溯法子集树模板实现图的遍历功能示例
Sep 05 Python
Numpy中转置transpose、T和swapaxes的实例讲解
Apr 17 Python
基于python实现名片管理系统
Nov 30 Python
pycharm运行程序时在Python console窗口中运行的方法
Dec 03 Python
IntelliJ IDEA安装运行python插件方法
Dec 10 Python
Tensorflow分类器项目自定义数据读入的实现
Feb 05 Python
Pytorch使用MNIST数据集实现CGAN和生成指定的数字方式
Jan 10 Python
Python类和实例的属性机制原理详解
Mar 21 Python
Softmax函数原理及Python实现过程解析
May 22 Python
python使用re模块爬取豆瓣Top250电影
Oct 20 Python
python实现遍历文件夹图片并重命名
Mar 23 #Python
Python3 mmap内存映射文件示例解析
Mar 23 #Python
Python3 io文本及原始流I/O工具用法详解
Mar 23 #Python
python实现横向拼接图片
Mar 23 #Python
Python操作Excel工作簿的示例代码(\*.xlsx)
Mar 23 #Python
python实现拼接图片
Mar 23 #Python
python使用PIL剪切和拼接图片
Mar 23 #Python
You might like
php可扩展的验证类实例(可对邮件、手机号、URL等验证)
2015/07/09 PHP
PHP中STDCLASS用法实例分析
2016/11/11 PHP
PHP预定义超全局数组变量小结
2018/08/20 PHP
PHP的new static和new self的区别与使用
2019/11/27 PHP
Js base64 加密解密介绍
2013/10/11 Javascript
javascript实现10个球随机运动、碰撞实例详解
2015/07/08 Javascript
学习JavaScript设计模式(策略模式)
2015/11/26 Javascript
jQuery检测滚动条是否到达底部
2015/12/15 Javascript
javascript实现下拉提示选择框
2015/12/29 Javascript
js闭包引起的事件注册问题介绍
2016/03/29 Javascript
JS动态给对象添加事件的简单方法
2016/07/19 Javascript
JS多文件上传的实例代码
2017/01/11 Javascript
原生JS实现导航下拉菜单效果
2020/11/25 Javascript
老生常谈angularjs中的$state.go
2017/04/24 Javascript
JS库之Three.js 简易入门教程(详解之一)
2017/09/13 Javascript
jQuery实现简易QQ聊天框
2020/02/10 jQuery
[07:09]2014DOTA2国际邀请赛-Newbee再次发威成功晋级决赛
2014/07/19 DOTA
[01:12:35]Spirit vs Navi Supermajor小组赛 A组败者组第一轮 BO3 第二场 6.2
2018/06/03 DOTA
[52:14]VG vs Serenity 2018国际邀请赛小组赛BO2 第一场 8.17
2018/08/20 DOTA
python重试装饰器示例
2014/02/11 Python
pandas 选择某几列的方法
2018/07/03 Python
使用Python监视指定目录下文件变更的方法
2018/10/15 Python
使用 Visual Studio Code(VSCode)搭建简单的Python+Django开发环境的方法步骤
2018/12/17 Python
python ipset管理 增删白名单的方法
2019/01/14 Python
numpy.array 操作使用简单总结
2019/11/08 Python
python实现百度OCR图片识别过程解析
2020/01/17 Python
Python os模块常用方法和属性总结
2020/02/20 Python
python实现扑克牌交互式界面发牌程序
2020/04/22 Python
AmazeUi Tree(树形结构) 应用小结
2020/08/17 HTML / CSS
英国在线药房:Chemist.co.uk
2019/03/26 全球购物
医生实习工作总结的自我评价
2013/09/27 职场文书
小小商店教学反思
2014/04/27 职场文书
评职称个人总结
2015/03/05 职场文书
2015年医院创卫工作总结
2015/04/22 职场文书
《去年的树》教学反思
2016/02/18 职场文书
Golang ort 中的sortInts 方法
2022/04/24 Golang