在 Python 中使用 zip_longest 时,For 循环不插入换行符 3

For-loop not inserting a line break when using zip_longest in Python 3

我正在写一个简单的文本比较工具。它需要两个文本文件——一个模板和一个目标——并使用两个 for 循环比较每一行中的每个字符。任何差异都使用 Unicode 完整块符号 (\u2588) 突出显示。在目标行比模板长的情况下,我使用 itertools.zip_longest 用填充值填充不存在的字符。

from itertools import zip_longest

def compare(filename1, filename2):
    
    file1 = open(filename1, "r")
    file2 = open(filename2, "r")
    
    for line1, line2 in zip_longest(file1, file2):
    
        for char1, char2 in zip_longest(line1, line2, fillvalue=None):
            
            if char1 == char2:
                print(char2, end='')
            
            elif char1 == None:
                print('\u2588', end='')

compare('template.txt', 'target.txt')
Template file:        Target file:

First line            First lineXX
Second line           Second line
Third line            Third line

但是,这似乎与 Python 的自动换行位置相混淆。当一行以这样的填充值结束时,不会产生换行符,给出这样的结果:

First line██Second line
Third line

而不是:

First line██
Second line
Third line

在重写脚本以使用 .append 和 .join(为保持简短而未显示)后问题仍然存在,但它允许我突出显示问题:

Result when both files are identical:

['F', 'i', 'r', 's', 't', ' ', 'l', 'i', 'n', 'e', '\n']
First line
['S', 'e', 'c', 'o', 'n', 'd', ' ', 'l', 'i', 'n', 'e', '\n']
Second line
['T', 'h', 'i', 'r', 'd', ' ', 'l', 'i', 'n', 'e']
Third line

Result when first line of target file has two more characters:

['F', 'i', 'r', 's', 't', ' ', 'l', 'i', 'n', 'e', '█', '█']
First line██['S', 'e', 'c', 'o', 'n', 'd', ' ', 'l', 'i', 'n', 'e', '\n']
Second line
['T', 'h', 'i', 'r', 'd', ' ', 'l', 'i', 'n', 'e']
Third line

如您所见,如果行的长度相同,Python 会自动添加一个换行符 \n,但是一旦涉及到 zip_longest,列表中的最后一个字符就是块,而不是换行符。为什么会这样?

在比较字符之前删除你的行并在每行之间打印新行:

from itertools import zip_longest

def compare(filename1, filename2):
    
    file1 = open(filename1, "r")
    file2 = open(filename2, "r")
    
    for line1, line2 in zip_longest(file1, file2):
        line1, line2 = line1.strip(), line2.strip()  # <- HERE

        for char1, char2 in zip_longest(line1, line2, fillvalue=None):
            
            if char1 == char2:
                print(char2, end='')

            elif char1 == None:
                print('\u2588', end='')
        print()  # <- HERE

compare('template.txt', 'target.txt')