web-dev-qa-db-fra.com

Comparer la différence de rapport entre deux fichiers dans python

J'ai 2 fichiers appelés "hôtes" (dans différents répertoires)

Je veux les comparer en utilisant python pour voir s'ils sont IDENTIQUES. S'ils ne sont pas identiques, je veux imprimer la différence sur l'écran.

Jusqu'à présent, j'ai essayé cela

hosts0 = open(dst1 + "/hosts","r") 
hosts1 = open(dst2 + "/hosts","r")

lines1 = hosts0.readlines()

for i,lines2 in enumerate(hosts1):
    if lines2 != lines1[i]:
        print "line ", i, " in hosts1 is different \n"
        print lines2
    else:
        print "same"

Mais quand je lance ça, je reçois

File "./audit.py", line 34, in <module>
  if lines2 != lines1[i]:
IndexError: list index out of range

Ce qui signifie que l'un des hôtes a plus de lignes que l'autre. Existe-t-il une meilleure méthode pour comparer 2 fichiers et signaler la différence?

33
Masster
import difflib

lines1 = '''
dog
cat
bird
buffalo
gophers
hound
horse
'''.strip().splitlines()

lines2 = '''
cat
dog
bird
buffalo
Gopher
horse
mouse
'''.strip().splitlines()

# Changes:
# swapped positions of cat and dog
# changed gophers to Gopher
# removed hound
# added mouse

for line in difflib.unified_diff(lines1, lines2, fromfile='file1', tofile='file2', lineterm=''):
    print line

Génère les éléments suivants:

--- file1
+++ file2
@@ -1,7 +1,7 @@
+cat
 dog
-cat
 bird
 buffalo
-gophers
-hound
+Gopher
 horse
+mouse

Ce diff vous donne des lignes entourant le contexte pour aider à faire comprendre en quoi le fichier est différent. Vous pouvez voir "chat" ici deux fois, car il a été retiré d'en bas "chien" et ajouté au-dessus.

Vous pouvez utiliser n = 0 pour supprimer le contexte.

for line in difflib.unified_diff(lines1, lines2, fromfile='file1', tofile='file2', lineterm='', n=0):
    print line

Sortie ceci:

--- file1
+++ file2
@@ -0,0 +1 @@
+cat
@@ -2 +2,0 @@
-cat
@@ -5,2 +5 @@
-gophers
-hound
+Gopher
@@ -7,0 +7 @@
+mouse

Mais maintenant, il est plein de lignes "@@" vous indiquant la position dans le fichier qui a changé. Supprimons les lignes supplémentaires pour le rendre plus lisible.

for line in difflib.unified_diff(lines1, lines2, fromfile='file1', tofile='file2', lineterm='', n=0):
    for prefix in ('---', '+++', '@@'):
        if line.startswith(prefix):
            break
    else:
        print line

Nous donnant cette sortie:

+cat
-cat
-gophers
-hound
+Gopher
+mouse

Maintenant, que voulez-vous qu'il fasse? Si vous ignorez toutes les lignes supprimées, vous ne verrez pas que "chien" a été supprimé. Si vous êtes content de simplement montrer les ajouts au fichier, vous pouvez le faire:

diff = difflib.unified_diff(lines1, lines2, fromfile='file1', tofile='file2', lineterm='', n=0)
lines = list(diff)[2:]
added = [line[1:] for line in lines if line[0] == '+']
removed = [line[1:] for line in lines if line[0] == '-']

print 'additions:'
for line in added:
    print line
print
print 'additions, ignoring position'
for line in added:
    if line not in removed:
        print line

Sortie:

additions:
cat
Gopher
mouse

additions, ignoring position:
Gopher
mouse

Vous pouvez probablement dire maintenant qu'il existe différentes façons "d'imprimer les différences" de deux fichiers, vous devrez donc être très précis si vous voulez plus d'aide.

56
rbutcher

La bibliothèque difflib est utile pour cela et vient dans la bibliothèque standard. J'aime le format diff unifié.

http://docs.python.org/2/library/difflib.html#difflib.unified_diff

import difflib
import sys

with open('/tmp/hosts0', 'r') as hosts0:
    with open('/tmp/hosts1', 'r') as hosts1:
        diff = difflib.unified_diff(
            hosts0.readlines(),
            hosts1.readlines(),
            fromfile='hosts0',
            tofile='hosts1',
        )
        for line in diff:
            sys.stdout.write(line)

Les sorties:

--- hosts0
+++ hosts1
@@ -1,5 +1,4 @@
 one
 two
-dogs
 three

Et voici une version douteuse qui ignore certaines lignes. Il peut y avoir des cas Edge qui ne fonctionnent pas, et il existe certainement de meilleures façons de le faire, mais ce sera peut-être assez bon pour vos besoins.

import difflib
import sys

with open('/tmp/hosts0', 'r') as hosts0:
    with open('/tmp/hosts1', 'r') as hosts1:
        diff = difflib.unified_diff(
            hosts0.readlines(),
            hosts1.readlines(),
            fromfile='hosts0',
            tofile='hosts1',
            n=0,
        )
        for line in diff:
            for prefix in ('---', '+++', '@@'):
                if line.startswith(prefix):
                    break
            else:
                sys.stdout.write(line[1:])
11
rbutcher
hosts0 = open("C:path\\a.txt","r")
hosts1 = open("C:path\\b.txt","r")

lines1 = hosts0.readlines()

for i,lines2 in enumerate(hosts1):
    if lines2 != lines1[i]:
        print "line ", i, " in hosts1 is different \n"
        print lines2
    else:
        print "same"

Le code ci-dessus fonctionne pour moi. Pouvez-vous indiquer à quelle erreur vous faites face?

3
Raj
import difflib
f=open('a.txt','r')  #open a file
f1=open('b.txt','r') #open another file to compare
str1=f.read()
str2=f1.read()
str1=str1.split()  #split the words in file by default through the spce
str2=str2.split()
d=difflib.Differ()     # compare and just print
diff=list(d.compare(str2,str1))
print '\n'.join(diff)
1
Azad Mehla

Vous pouvez ajouter une instruction conditionnelle. Si votre tableau va au-delà de l'index, cassez et imprimez le reste du fichier.

1
user2835809