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 10 Python
pycharm+django创建一个搜索网页实例代码
Jan 24 Python
python docx 中文字体设置的操作方法
May 08 Python
QML使用Python的函数过程解析
Sep 26 Python
django数据模型(Model)的字段类型解析
Dec 25 Python
pytorch 实现tensor与numpy数组转换
Dec 27 Python
深入了解如何基于Python读写Kafka
Dec 31 Python
Pytorch之finetune使用详解
Jan 18 Python
Python 字符串池化的前提
Jul 03 Python
python语音识别指南终极版(有这一篇足矣)
Sep 09 Python
Python离线安装各种库及pip的方法
Nov 28 Python
5行Python代码实现一键批量扣图
Jun 29 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中使用cookie来保存用户登录信息的实现代码
2012/03/08 PHP
解析PHP函数array_flip()在重复数组元素删除中的作用
2013/06/27 PHP
Linux下创建nginx脚本-start、stop、reload…
2014/08/03 PHP
php数组分页实现方法
2016/04/30 PHP
php微信扫码支付 php公众号支付
2019/03/24 PHP
Yii2.0框架behaviors方法使用实例分析
2019/09/30 PHP
一个简单的js渐显(fadeIn)渐隐(fadeOut)类
2010/06/19 Javascript
bootstrap table 服务器端分页例子分享
2015/02/10 Javascript
javascript+ajax实现产品页面加载信息
2015/07/09 Javascript
JS hashMap实例详解
2016/05/26 Javascript
Angular.js实现注册系统的实例详解
2016/12/18 Javascript
JS简单生成随机数(随机密码)的方法
2017/05/11 Javascript
详解原生js实现offset方法
2017/06/15 Javascript
canvas基础绘制-绚丽倒计时的实例
2017/09/17 Javascript
详解Vue SPA项目优化小记
2018/07/03 Javascript
Layui数据表格之获取表格中所有的数据方法
2018/08/20 Javascript
js实现鼠标拖拽缩放div实例代码
2019/03/25 Javascript
详解服务端预渲染之Nuxt(介绍篇)
2019/04/07 Javascript
微信小程序实现form表单本地储存数据
2019/06/27 Javascript
Vue 实现CLI 3.0 + momentjs + lodash打包时优化
2019/11/13 Javascript
vue实现短信验证码登录功能(流程详解)
2019/12/10 Javascript
ubuntu环境下python虚拟环境的安装过程
2018/01/07 Python
Python实现合并两个有序链表的方法示例
2019/01/31 Python
Python把对应格式的csv文件转换成字典类型存储脚本的方法
2019/02/12 Python
python pygame实现方向键控制小球
2019/05/17 Python
Python企业编码生成系统之主程序模块设计详解
2019/07/26 Python
在 Windows 下搭建高效的 django 开发环境的详细教程
2020/07/27 Python
Django数据库迁移常见使用方法
2020/11/12 Python
美国最大的宠物用品零售商:PetSmart
2016/11/14 全球购物
英国最大的在线奢侈手表零售商:Jura Watches
2018/01/29 全球购物
AJAX应用和传统Web应用有什么不同
2013/08/24 面试题
医学专业大学生求职的自我评价
2013/11/27 职场文书
中学实习教师自我鉴定
2013/12/12 职场文书
2015年家长学校工作总结
2015/04/22 职场文书
九年级化学教学反思
2016/02/22 职场文书
2016年“5.12”国际护士节活动总结
2016/04/06 职场文书