如何在Python中逐行比较两个文件?

2,422 阅读6分钟

本教程研究了如何在Python中比较两个文件的各种方法。我们将介绍读取两个文件并逐行比较,以及使用可用的模块来完成这项常见的任务。

在Python中比较两个文件的方法有很多。Python 提供了用于这一目的的模块,包括 filecmp 和 difflib 模块。

下面的 Python 3 例子对比了确定两个文件是否包含相同数据的各种方法。我们将使用 Python 3 内置的函数和模块,所以不需要下载额外的软件包。

逐行比较两个文本文件

我们可以使用open()函数比较两个文本文件,读取文件中包含的数据。open()函数将在本地目录中寻找一个文件并试图读取它。

在这个例子中,我们将比较两个包含电子邮件数据的文件。这两个电子邮件的列表,我们被告知,可能不完全相同。我们将让 Python 为我们检查这些文件。使用readlines() 方法,可以从文本文件中提取行数。

emails_A.txt
l.bennett@randomail.com
m.henderson@randomail.com
j.barrett@randomail.com
t.casey@randomail.com
m.wells@randomail.com

emails_B.txt
v.thompson@randomail.com
m.henderson@randomail.com
t.carroll@randomail.com
s.barnes@randomail.com
m.wells@randomail.com

一旦数据被提取出来,一个**for循环** 被用来逐行比较这些文件。如果这几行不匹配,用户就会收到一条信息,告诉他们哪里发生了不匹配。我们将包括数据本身,这样用户可以很容易地追踪到不同的行。

例子。使用Python来比较电子邮件列表

file1 = open("emails_A.txt",'r')
file2 = open("emails_B.txt",'r')

file1_lines = file1.readlines()
file2_lines = file2.readlines()

for i in range(len(file1_lines)):
    if file1_lines[i] != file2_lines[i]:
        print("Line " + str(i+1) + " doesn't match.")
        print("------------------------")
        print("File1: " + file1_lines[i])
        print("File2: " + file2_lines[i])

file1.close()
file2.close()

输出

Line 1 doesn't match.
------------------------
File1: l.bennett@randomail.com

File2: v.thompson@randomail.com

Line 3 doesn't match.
------------------------
File1: j.barrett@randomail.com

File2: t.carroll@randomail.com

Line 4 doesn't match.
------------------------
File1: t.casey@randomail.com

File2: s.barnes@randomail.com

使用 filecmp 模块来比较文件

filecmp 模块包括在 Python 中处理文件的功能。具体来说,这个模块是用来比较两个或多个文件之间的数据。我们可以使用filecmp.cmp() 方法来完成这个任务。如果文件匹配,该方法将返回True,如果不匹配,则返回False

这个例子使用了三个文件。第一个和第三个是相同的,而第二个则略有不同。我们将使用 filecmp.cmp() 方法,用 Python 来比较这些文件。

punctuation1.txt
吃你的饭。
我想感谢我的父母、珍妮特和上帝。
我很抱歉我关心你。
她真的很喜欢做饭,喜欢她的家人和她的猫。

punctuation2.txt
吃吧。你是晚餐!
我想感谢我的父母、珍妮特和上帝。
我很抱歉。我很关心你。
她真的很喜欢烹饪她的家人和她的猫。

punctuation3.txt
吃你的晚餐。
我想感谢我的父母,珍妮特和上帝。
我很抱歉我关心你。
她真的很喜欢烹饪,她的家庭和她的猫咪。

在我们使用filecmp模块之前,我们需要导入它。我们还需要导入os模块,它将允许我们使用目录中的路径来加载文件。在这个例子中,我们使用了一个自定义函数来完成比较。

在我们比较了文件之后,我们可以看到数据是否匹配, 最后,我们会提醒用户注意结果。

例子。用filecmp.cmp()比较两个文件

import filecmp
import os

# notice the two backslashes
file1 = "C:\\Users\jpett\\Desktop\\PythonForBeginners\\2Files\\punctuation1.txt"
file2 = "C:\\Users\jpett\\Desktop\\PythonForBeginners\\2Files\\punctuation2.txt"
file3 = "C:\\Users\jpett\\Desktop\\PythonForBeginners\\2Files\\punctuation3.txt"

def compare_files(file1,file2):
    compare = filecmp.cmp(file1,file2)

    if compare == True:
        print("The files are the same.")
    else:
        print("The files are different.")

compare_files(file1,file2)
compare_files(file1,file3)

输出

The files are different.
The files are the same.

使用difflib模块比较两个文件

difflib模块对于比较文本并找出它们之间的差异非常有用。这个Python 3模块是预装在语言中的。它包含许多用于比较文本体的有用函数。

首先,我们将使用unified_diff()函数来确定两个数据文件之间的不匹配。这些文件包含了虚构学生的信息,包括他们的名字和平均分。

其次,我们将比较这些学生记录,检查学生的成绩在2019年到2020年的变化。我们可以使用unified_diff()函数来做这件事。下面的例子利用了with语句来读取文件数据。通过使用Python的with语句,我们可以安全地打开和读取文件。

student_gpa_2019.txt
Chelsea Walker 3.3
Caroline Bennett 2.8
Garry Holmes 3.7
Rafael Rogers 3.6
Patrick Nelson 2.1

student_gpa_2020.txt
Chelsea Walker 3.6
Caroline Bennett 2.7
Garry Holmes 3.7
Rafael Rogers 3.7
Patrick Nelson 2.1

例子。比较学生的GPA

import difflib

with open("student_gpa_2019.txt",'r') as file1:
    file1_contents = file1.readlines()
with open("student_gpa_2020.txt",'r') as file2:
    file2_contents = file2.readlines()

diff = difflib.unified_diff(
    file1_contents, file2_contents, fromfile="file1.txt",
    tofile="file2.txt", lineterm='')

for line in diff:
    print(line)

输出

--- file1.txt
+++ file2.txt
@@ -1,5 +1,5 @@
-Chelsea        Walker 3.3
-Caroline       Bennett 2.8
+Chelsea        Walker 3.6
+Caroline       Bennett 2.7
 Garry  Holmes 3.7
-Rafael Rogers 3.6
+Rafael Rogers 3.7
 Patrick        Nelson 2.1

看一下输出结果,我们可以看到difflib模块的作用远远超过逐行比较文本文件。unified_diff()函数还提供了一些关于发现的差异的上下文。

在Python中逐行比较两个.csv文件

逗号分隔值文件被用来在程序之间交换数据。Python 也提供了处理这些文件的工具。通过使用csv模块,我们可以快速访问 csv 文件中的数据。

使用 csv 模块,我们将比较两个数据文件并找出不匹配的行。这些文件包含员工记录,包括每个员工的名字、姓氏和电子邮件。这些数据是随机产生的,但我们要假装我们的雇员急需我们完成比较。

employeesA.csv
"名", "姓", "电子邮件"
"David", "Crawford", "d.crawford@randomail.com"
"Sarah", "Payne", "s.payne@randomail.com"
"Robert", "Cooper", "r.cooper@randomail.com"
"Aida", "Alexander", "a.alexander@randomail.com"
"Valeria", "Douglas", "v.douglas@randomail.com"

雇员B。csv
"名", "姓", "电子邮件"
"Andrew", "Crawford", "a.crawford@randomail.com"
"Sarah", "Payne", "s.payne@randomail.com"
"Robert", "Cooper", "r.cooper@randomail.com"
"Agata", "Anderson", "a.anderson@randomail.com"
"Miley", "Holmes", "m.holmes@randomail.com"

一旦我们有了雇员数据,我们就可以使用reader()函数来读取它。包含在csv模块中,reader()函数可以解释csv数据。在收集到数据后,我们可以使用Python将数据转换为一个列表。

最后,使用for循环,我们将比较两个列表的元素。每个元素都将包含雇员数据文件中的一行。这样,我们可以遍历列表,发现哪些行是不一样的。

Python程序将逐行比较这些文件。结果是,我们可以找出雇员数据文件之间的所有差异。

例子。使用csv模块来比较雇员数据文件

import csv

file1 = open("employeesA.csv",'r')
file2 = open("employeesB.csv",'r')

data_read1= csv.reader(file1)
data_read2 = csv.reader(file2)

# convert the data to a list
data1 = [data for data in data_read1]
data2 = [data for data in data_read2]

for i in range(len(data1)):
    if data1[i] != data2[i]:
        print("Line " + str(i) + " is a mismatch.")
        print(f"{data1[i]} doesn't match {data2[i]}")

file1.close()
file2.close()

输出

Line 1 is a mismatch.
['David', 'Crawford', 'd.crawford@randomail.com'] doesn't match ['Andrew', 'Crawford', 'a.crawford@randomail.com']
Line 4 is a mismatch.
['Aida', 'Alexander', 'a.alexander@randomail.com'] doesn't match ['Agata', 'Anderson', 'a.anderson@randomail.com']
Line 5 is a mismatch.
['Valeria', 'Douglas', 'v.douglas@randomail.com'] doesn't match ['Miley', 'Holmes', 'm.holmes@randomail.com']

总结

Python 提供了许多工具来比较两个文本文件,包括 csv 文件。在这篇文章中,我们已经讨论了Python 3中的许多函数和模块。此外,我们已经看到了如何使用它们在Python中逐行比较文件。

通过发现新的模块,我们可以编写让我们的生活更轻松的程序。我们日常使用的许多程序和网络应用都是由Python驱动的。