Python beginner: TypeError: объект 'NoneType' не повторяется: как его решить? - PullRequest
0 голосов
/ 06 апреля 2020

Доброе утро,

Я пытаюсь извлечь предложения, ссылающиеся на рецензию, и их ярлык в файле xml. Проблема, с которой я сталкиваюсь, заключается в том, что не все предложения имеют метку, поэтому я извлекаю только те предложения, которые имеют метку, а затем возвращаю два значения: обзор и метку. По непонятной причине я получаю эту ошибку:


Avant 75 on n'a pas isolé puis après, au fur et à mesure des règlementations, on en a mis. Avant 75, il suffit d'en mettre et on fait tout de suite de grosses économies. motivation
Avant 75 on n'a pas isolé puis après, au fur et à mesure des règlementations, on en a mis. Avant 75, il suffit d'en mettre et on fait tout de suite de grosses économies. motivation
Traceback (most recent call last):
  File "flue/extract_split_cls_c.py", line 164, in <module>
    main()
  File "flue/extract_split_cls_c.py", line 87, in main
    review_text, label = get_review_labels(text, category=category, do_lower=args.do_lower)
TypeError: 'NoneType' object is not iterable

При печати метки и извлеченной рецензии терминал отображает все предложения с их метками, но когда я хочу вернуть метку и просмотреть как значения и присвойте им переменную, появится ошибка, упомянутая выше. Это потому, что есть некоторые предложения, у которых нет метки, и система не знает, что делать, даже когда я указываю в сценарии, что я хочу только предложения с меткой?

Вот скрипт:

import os
import numpy as np
import math
import random
import re
import csv
import argparse
import sys

from lxml import etree

sys.path.append(os.getcwd())

from tools.clean_text import cleaner
from xlm.utils import bool_flag


def review_extractor(text, category='verbatim', do_lower=False):
    """
    Extract review and label
    """

    tree = etree.fromstring(bytes(text, encoding='utf-8'))
    for e in tree.findall(".//*[@fmc]"):
      label = e.xpath("./@fmc")[0]
      for c in e.findall("./part"):
        # print value of "fmc" attribute and text of child element
        print(c.text, label)
        #print(f"{label:15}{c.text}")
        return c.text, label


def get_review_labels(text, category='verbatim', do_lower=False):
    """
    Input: line
    Returns cleaned review and label
    """
    review_text, label = review_extractor(text, category=category, do_lower=do_lower)
    #review_text = cleaner(review_text, rm_new_lines=True)
    print(review_text, label)
    return review_text, label


def main():
    parser = argparse.ArgumentParser()

    parser.add_argument('--indir', type=str, help='Path to raw data directory.')
    parser.add_argument('--outdir', type=str, help='Path to processed data directory.')
    parser.add_argument('--do_lower', type=bool_flag, default='False', help='True if do lower case, False otherwise.')
    parser.add_argument('--val_ratio', type=float, default=0.2, help='Ratio to split data for validation.')
    parser.add_argument('--use_hugging_face', type=bool_flag, default='False', help='Prepare data to run fine-tuning using \
                                                                                    Hugging Face Transformer library')

    args = parser.parse_args()

    indir = os.path.expanduser(args.indir)
    outdir = os.path.expanduser(args.outdir)

    category = 'verbatim'
    lang = 'fr'
    val_ratio = args.val_ratio

    train_fname = 'train.tsv' if args.use_hugging_face else 'train_0.tsv' 
    val_fname = 'dev.tsv' if args.use_hugging_face else 'valid_0.tsv' 
    test_fname = 'test.tsv' if args.use_hugging_face else 'test_0.tsv'  

    #for category in categories:
    #print('-'*20)
    path = os.path.join(indir, lang, category)
    splts = ['train', 'test']

    for s in splts:
        review_texts = []
        labels = []
        stats = []


        with open(os.path.join(path, s+'.review'), 'rt', encoding='utf-8') as f_in:
            next(f_in)
            text = f_in.read()
            print(text) # to display whole file


            review_text, label = get_review_labels(text, category=category, do_lower=args.do_lower)
            #review_text, label = review_extractor(text, category=category, do_lower=args.do_lower) 
            review_texts.append(review_text)
            labels.append(label)
            stats.append(len(review_text.split()))



        #assert len(review_texts) == len(labels) == i


        out_path = os.path.join(outdir, category)
        if not os.path.exists(out_path):
            os.makedirs(out_path)




if __name__ == "__main__":
    main()

файл выглядит так (есть два файла: тестовый и обучающий), но формат тот же:


<corpus><verbatim id="15" etude="EC1_Elec" elec="oui" niveau="1" critere="" origine="IW" type="discours">
<part code="EC1_Elec_IW04_0">Dans le cadre du projet GOSPELS, on a un système équivalent, avec des alertes qui clig                     notent quand la température ou les consommations dérivent, c'est quelque chose qui devrait être de base mais qui re                     ste encore à généraliser.</part></verbatim>

<verbatim id="18" etude="EC1_Elec" elec="oui" niveau="1" critere="1.3" origine="IW" type="discours">
<part code="EC1_Elec_IW04_0">Ça existe sur des gros parcs Hlm mais c'est macro. Vous faites varier la ventillation,                      etc. nous on n'a pas ces équipements là. Piloter les équipements avec un outil dédié.
</part>
</verbatim>

<verbatim id="30" etude="EC1_Elec" elec="oui" niveau="2" critere="" origine="IW" type="discours" fmc="motivation">
<part code="EC1_Elec_IW01_0">Avant 75 on n'a pas isolé puis après, au fur et à mesure des règlementations, on en a                      mis. Avant 75, il suffit d'en mettre et on fait tout de suite de grosses économies.</part>
</verbatim>

<verbatim id="54" etude="EC1_Elec" elec="oui" niveau="1" critere="" origine="IW" type="discours" fmc="condition">
<part code="EC1_Elec_IW10_0">Le deuxième boitier, il est où ? s'il y en a un qui est à l'intérieur et qui remplace                      un bout de l'isolation, il est caché OK. Mais le deuxième, si c'est un mur extérieur, est ce qu'il est posé directe                     ment sur le mur ? ça veut dire qu'il doit être esthétiquement intégrable du point de vue architectural mais aussi q                     u'il résiste à tous les éléments extérieurs : la pluie, la neige, etc.
</part></verbatim>

<verbatim id="55" etude="EC1_Elec" elec="oui" niveau="1" critere="1.1" origine="IW" type="discours" fmc="motivation                     ">
<part code="EC1_Elec_IW10_0">Le concept d'alarmes est pas mal, il faut voir comment c'est géré mais c'est pas mal.
</part>
</verbatim>

<verbatim id="68" etude="EC1_Elec" elec="oui" niveau="" critere="" origine="IW" type="discours" fmc="condition">
<part code="EC1_Elec_IW01_0">« intéressant » mais intéressant pour le petit pourcentage de cas ou pour objectiver u                     ne situation. Mais on pourrait imaginer un truc qu'on colle, on pianote un truc et… 'oula, U=0,272'et là il va dire                      'il est sérieux', même si c'est du flan.
</part></verbatim>

        <verbatim id="69" etude="EC1_Elec" elec="oui" niveau="4" critere="" origine="IW" type="discours">
                <part code="EC1_Elec_IW01_0">ROI, 5 à 10 ans. Si l'énergie explose, ça deviendra rentable de mettre                      l'isolant. Dans les bâtiments où il n'y en a pas, on bataille parce que ça a un coût. Mais pour les bâtiments plus                      récents et qu'on récupère 100€ par an, ce n'est pas suffisant parce qu'on ne récupère jamais les 3000€ d'investiss                     ements.
                </part>
        </verbatim>
        <verbatim id="80" etude="EC1_Elec" elec="oui" niveau="1" critere="" origine="IW" type="discours">
                <part code="EC1_Elec_IW03_0">La caractériser en amont, je vois bien, la suivre dans le temps, j'ai                      du mal à voir si ça a une vraie pertinence. Comme ça, ça me parait bizarre que la performance change dans le temps.
                </part>
        </verbatim>
        <verbatim id="93" etude="EC1_Elec" elec="oui" niveau="2" critere="" origine="IW" type="discours">
                <part code="EC1_Elec_IW05_0">Dans le cadre d'opérations, on pourrait l'utiliser pour des procédés q                     u'on maitrise mal ou des matériaux comme le bois avec un isolant qui peut prendre l'humidité ou des choses comme ça                     .
                </part>
        </verbatim>
        <verbatim id="134" etude="EC1_Elec" elec="oui" niveau="2" critere="2.4" origine="IW" type="discours" fmc="m                     otivation">
                <part code="EC1_Elec_IW03_0">On est souvent assez loin des objectifs qu'on se fixe et si au départ                      on n'est pas bon dans les hypothèses qu'on a pu prendre, forcément ça va se retrouver derrière. On peut être plus p                     récis dans l'approche du bâtiment.
                </part>
        </verbatim>
        <verbatim id="147" etude="EC1_Elec" elec="oui" niveau="2" critere="" origine="IW" type="discours">
                <part code="EC1_Elec_IW08_0">La performance se situe dans le choix du verre, dans les joints de cal                     feutrement mais aussi dans le joint entre l'ouvrant et le dormant. Et votre boitier ne mesure pas ça. Dans le temps                     , ce sont ces dispositifs qui se dégradent ; bien plus vite que la paroi.
                </part>
        </verbatim>
        <verbatim id="160" etude="EC1_Elec" elec="oui" niveau="2" critere="" origine="IW" type="discours" fmc="cond                     ition">
                <part code="EC1_Elec_IW03_0">Suivre la performance dans le temps m'intéresse mais j'ai des indicate                     urs simples, c'est la consommation d'une chaufferie. Si la consommation augmente, c'est qu'il y a un problème. C'es                     t soit lié à la froidure, soit à l'usage des locataires, soit à une mauvaise maitrise des équipements ou… C'est moi                     ns lié à la performance d'une enveloppe parce que je ne vois pas comment l'enveloppe peut perdre de sa performance                      mais peut-être que je me trompe.
                </part>
        </verbatim>
        <verbatim id="171" etude="EC1_Elec" elec="oui" niveau="2" critere="" origine="IW" type="discours" fmc="cond                     ition">
                <part code="EC1_Elec_IW04_0">Dans le cadre d'un diagnostic plus large, si l'équipement est proposé                      par le prestataire et que le matériau est plus performant, ça peut être utile. On n'a pas toujours la performance d                     e la paroi.
                </part>
        </verbatim>
        <verbatim id="224" etude="EC1_Elec" elec="oui" niveau="2" critere="" origine="IW" type="discours" fmc="moti                     vation">
                <part code="EC1_Elec_IW10_0">tu poses les blocs et tu as directement la performance de ton envelopp                     e. Ça permet de se dire tout de suite si l'isolant est complètement affaissé, s'il est encore performant ou plus du                      tout. Donc ça peut permettre de préconiser un remplacement, un changement ou la conservation pendant encore plusie                     urs années.
                </part>
        </verbatim>
</corpus>

Как вы можете увидеть пару тегов , не имеют атрибута "fm c".

Что я ожидал, функция вернет обзор и метку в переменной, созданной ближе к концу скрипта, так что я смогу написать их в файл TSV и подсчитать количество предложений на ярлык. но так как я получил эту ошибку, я не мог перейти к написанию сценария. Я надеюсь, что пример может быть воспроизводимым.

1 Ответ

1 голос
/ 06 апреля 2020

Проблема в

label = e.xpath("./@fmc")[0]

Если нет fmc, тогда вы получите

label = None[0]

и у вас есть ошибка 'NoneType' object is not iterable

Вы должны проверить значение, прежде чем вы получите [0] - как это

label = e.xpath("./@fmc")
if label:
   label = label[0]
else:
   label = "some default label"
...