14

I am using Python 2.6 and I want to create a simple GUI with two side-by-side text panes comparing two text files (file1.txt & file2.txt) .

I am using difflib but it is not clear for me how to produce a result similar to the sdiff Unix command.

In order to reproduce a side-by-side comparison, I need difflib to return two variables file1_diff and file2_diff, for instance.

I have also considered to use sdiff output directly and parse it to separate the panes but it turned out not to be as easy as it seems... Any hints?

zml
  • 507
  • 5
  • 14
  • IIRC you can use the difflib internals and write your own side-by-side display routines. If not you can take a look at [meld](http://meldmerge.org/)'s sources as that is a Python based side-by-side diff tool – Anthon Jun 24 '15 at 09:43
  • Are you asking how to write the GUI, or how to get difflib to return side-by-side diffs? – Bryan Oakley Jun 24 '15 at 10:36
  • Sorry, I will update the question to be more clear. What I want is to get a diff in two separate strings so I can output them in two different panes. Something like the sdiff command output but with the two columns 'unmerged ' – zml Jun 24 '15 at 12:24

3 Answers3

1

How about something like this?

>>> a = ['cat', 'dog', 'horse']
>>> b = ['cat', 'horse', 'chicken']
>>> comparison = list(l for l in difflib.Differ().compare(a,b) if not l.startswith('?'))
>>> left = [l[2:] if l.startswith((' ', '-')) else '' for l in comparison]
>>> right = [l[2:] if l.startswith((' ', '+')) else '' for l in comparison]
>>> left
['cat', 'dog', 'horse', '']
>>> right
['cat', '', 'horse', 'chicken']
pschanely
  • 81
  • 1
  • 6
1

You can use difflib.Differ to return a single sequence of lines with a marker at the start of each line which describes the line. The markers tell you the following information about the line:

Marker Description
'- ' line unique to file 1
'+ ' line unique to file 2
' ' line common to both files
'? ' line not present in either input files

You can use this information to decide how to display the data. For example, if the marker is , you put the line both in the left and right widgets. If it's + , you could put a blank line on the left and the actual line on the right showing that the line is unique to the text on the right. Likewise, - means the line is unique to the left.

For example, you can create two text widgets t1 and t2, one for the left and one for the right. You can compare two files by creating a list of lines for each and then passing them to the compare method of the differ and then iterating over the results.

t1 = tk.Text(...)
t2 = tk.Text(...)

f1 = open("file1.txt", "r").readlines()
f2 = open("file2.txt", "r").readlines()

differ = difflib.Differ()
for line in differ.compare(f1, f2):
    marker = line[0]
    if marker == " ":
        # line is same in both
        t1.insert("end", line[2:])
        t2.insert("end", line[2:])

    elif marker == "-":
        # line is only on the left
        t1.insert("end", line[2:])
        t2.insert("end", "\n")

    elif marker == "+":
        # line is only on the right
        t1.insert("end", "\n")
        t2.insert("end", line[2:])

The above code ignores lines with the marker ? since those are extra lines that attempt to bring attention to the different characters on the previous line and aren't actually part of either file. You could use that information to highlight the individual characters if you wish.

Bryan Oakley
  • 310,202
  • 36
  • 445
  • 584
-2

I've tried to do files diff with difflib.context_diff:

diff = difflib.context_diff(fromlines, tolines, fromfile='file1.txt', tofile='file2.txt')
sys.stdout.writelines(diff)

In this case your output will be something like this:

*** file1.txt
--- file2.txt
***************
*** 1,6 ****
! aasdf
  qwer
  123
! poiu
! xzcv34
  xzcv
--- 1,6 ----
! asdf
  qwer
+ mnbv
  123
! cvnn
  xzcv

In this case you'll be able easily to separate each file diff, but I'm not sure if you will be satisfied by the output of context_diff. You haven't mentioned in what way you're using the difflib.

Hett
  • 1,253
  • 2
  • 12
  • 17
  • Please run the `sdiff` or `diff -y` on file1.txt and file2.txt and check the ouput. That is my goal, to reproduce that kind of output in two different files. – zml Jun 24 '15 at 13:31
  • Yep, I've tried and it seems to me, that the only way to get something like that is to use `HtmlDiff()` method. The output will look something like [this](http://tinypic.com/r/opy43q/8). In this case you can write the html output to the file, which is basically a table and than get the content from that file. Although how are you going to show it it's up to you. Are you going to output result to the console (linux) or show it in gui (windows or gtk)? – Hett Jun 24 '15 at 14:09
  • My idea is to display it in a GUI as in meld or kompare tools. – zml Jun 24 '15 at 14:10
  • In that case I will recommend to use [HtmlDiff ](https://docs.python.org/2/library/difflib.html#difflib.HtmlDiff), parse the html result (there'll be no need to write column separation logic, cause files are already in the table by columns and rows) and than you can use the result to output in the gui controls. Sorry I've no experience in the gui controls, so I will not be able to help you on that one. If you'll have any further question on html parsing, let me know. – Hett Jun 24 '15 at 14:16