

特定のディレクトリ内のすべてのファイル情報をElementTreeでXMLに蓄積し、差分をチェックするスクリプトを作成しています。  
XMLは以下のようなフォーマットです。

[code]

    <root>
        <record author="pcname" time="2021-11-27">
            <file file_name="a.txt" md5="148991">
            <file file_name="b.txt" md5="148992">
            <file file_name="c.txt" md5="148993">
        </record>
        <record author="pcname" time="2021-11-28">
            <file file_name="a.txt" md5="148991">
            <file file_name="b.txt" md5="148992">
            <file file_name="c.txt" md5="148993">
            <file file_name="new.txt" md5="148993">
        </record>
    </root>
    
[/code]

最新のRecordと一つ前のRecordタグの差分をとるために以下のコードを書きました。  
(HistoryXmlは私が新しく定義したクラス名です。)

[code]

    @staticmethod
    def __existSameFileName(files:list[Element],name_value:str ) -> bool:
        for file in files:
            if(file.get('file_name') == name_value):
                return True
        return False
    
    @staticmethod
    def __diffDeleted(prev_files:list[Element], last_files:list[Element]):
        for prev_file in prev_files:
            prev_file_name = prev_file.get('file_name')
            if not (HistoryXml.__existSameFileName(last_files, prev_file_name)):
                # deleted file found
                print('deleted:' + prev_file_name)
    
    @staticmethod
    def __diffNew(prev_files:list[Element], last_files:list[Element]):
        for last_file in last_files:
            file_name = last_file.get('file_name')
            if not (HistoryXml.__existSameFileName(prev_files, file_name)):
                # new file found
                print('new:' + file_name)
    
    def diffLast(self):
        record_list = self.__root.findall('record')
        prev_record = record_list[-2] # 1つ前データ
        last_record = record_list[-1] # 最新のデータ
        prev_files = prev_record.findall('file')
        last_files = last_record.findall('file')
        HistoryXml.__diffNew(prev_files=prev_files,last_files=last_files)
        HistoryXml.__diffDeleted(prev_files=prev_files,last_files=last_files)
    
[/code]

上記のXMLの期待値は"new:new.txt"のみの出力ですが、実際には"new:new.txt"と"deleted:new.txt"どちらも出力されてしまいます。

そこで私は以下のコードを書いてテストしましたが、期待通り'newfile found in prev!'が出力します。

[code]

    def diffLast(self):
        record_list = self.__root.findall('record')
        prev_record = record_list[-2]
        last_record = record_list[-1]
        prev_files = prev_record.findall('file')
        last_files = last_record.findall('file')
        if(HistoryXml.__existSameFileName(prev_files ,'new.txt')):
            print('newfile found in prev!')
        
        if(HistoryXml.__existSameFileName(last_files ,'new.txt')):
            print('newfile found in last!')
    
[/code]


CC BY-SA 4.0
2021-11-28T11:18:55.870
83846
2021-11-28T16:26:39.070
2021-11-28T12:15:00.033
3060
49264
question
python python3
Python ElementTreeのfindall()で取得したリストが意図しない挙動になる。


全て `staticmethod` なので関数に置き換えて実行してみました(内容は変更していません)。期待通りの結果ですね(`new:new.txt`
のみ出力)。

[code]

    import xml.etree.ElementTree as ET
    
    def existSameFileName(files, name_value):
        for file in files:
            if(file.get('file_name') == name_value):
                return True
        return False
    
    def diffDeleted(prev_files, last_files):
        for prev_file in prev_files:
            prev_file_name = prev_file.get('file_name')
            if not (existSameFileName(last_files, prev_file_name)):
                # deleted file found
                print('deleted:' + prev_file_name)
    
    def diffNew(prev_files, last_files):
        for last_file in last_files:
            file_name = last_file.get('file_name')
            if not (existSameFileName(prev_files, file_name)):
                # new file found
                print('new:' + file_name)
    
    def diffLast(root):
        record_list = root.findall('record')
        prev_record = record_list[-2] # 1つ前データ
        last_record = record_list[-1] # 最新のデータ
        prev_files = prev_record.findall('file')
        last_files = last_record.findall('file')
        diffNew(prev_files=prev_files,last_files=last_files)
        diffDeleted(prev_files=prev_files,last_files=last_files)
    
    if __name__ == '__main__':
    
        xml_text = '''
    <root>
        <record author="pcname" time="2021-11-27">
            <file file_name="a.txt" md5="148991"/>
            <file file_name="b.txt" md5="148992"/>
            <file file_name="c.txt" md5="148993"/>
        </record>
        <record author="pcname" time="2021-11-28">
            <file file_name="a.txt" md5="148991"/>
            <file file_name="b.txt" md5="148992"/>
            <file file_name="c.txt" md5="148993"/>
            <file file_name="new.txt" md5="148993"/>
        </record>
    </root>
    '''.strip()
    
        root = ET.fromstring(xml_text)
        diffLast(root)
    
[/code]

**実行結果**

[code]

    new:new.txt
    
[/code]


CC BY-SA 4.0
2021-11-28T16:26:39.070
83853
2021-11-28T16:26:39.070
47127
83846
answer