【问题标题】:Python beginner :TypeError: 'NoneType' object is not iterable : how to solve it?Python初学者:TypeError:'NoneType'对象不可迭代:如何解决?
【发布时间】:2020-04-06 09:30:18
【问题描述】:

早上好,

我正在尝试在 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()

文件看起来像这样(有两个文件:test 和 train),但格式相同:


<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>

你可以看到一些标签,没有属性“fmc”。

我期望该函数返回在脚本末尾创建的变量中的评论和标签,以便我能够将它们写在 tsv 文件中并计算每个标签的句子数。但由于我得到了那个错误,我无法继续编写脚本。我希望这个例子可以重现。

【问题讨论】:

  • NoneType is not iterable 意味着你在某个地方得到了None,你尝试做None[index]。可能在xpath(...)[0] 中,你从xpath() 得到None,你得到None[0]。在获得 [0] 之前,您应该检查 xpath - 即。 result = xpath(...)if result: result = result[0]
  • 我尝试插入行来检查值,但在那之后我应该做的是,我只是添加我的以下代码,它在终端中只打印两个句子文件有超过 5 个句子有标签(fmc)

标签: python python-3.x xml xml-parsing extract


【解决方案1】:

问题出在

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"

【讨论】:

  • 或使用e.get("fmc", "some default label")
  • 使用您的解决方案只打印两个句子而不是所有句子: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") if label : label == label[0] else: label = "some default label" for c in e.findall("./part"): print(c.text, label) return c.text, label
  • 我的回答解决了错误问题。现在你有不同的问题,与所描述的问题无关 - 你在代码中有不同的错误。至于我,你的问题是returnreview_extractor 中的for-loop - 所以你在第一个元素之后退出循环并且你永远不会得到其他元素。您应该创建包含所有结果的列表并使用 return 外部循环 - return list_with_all values
  • 我明白你说什么,但在我的情况下,我有一个函数清理器,它作为输入文本而不是类类型列表,所以如果我创建一个包含我所有评论和所有标签的列表,那函数会给我一个错误,有没有另一种方法可以返回唯一的文本而不是文本列表(评论)??
  • 如果您有许多独特的文本,那么您必须创建包含所有独特项目的列表。并使用 for-loop 来处理它们。在for-loop 中使用return c.text, label,你只会得到第一个唯一的项目。在for-loop 之后使用return c.text, label,您将获得最后一项。您必须将所有内容放入列表并返回列表。后来使用for-loop 两个工作。标准规则:如果您有很多项目,那么您将不得不在某个地方使用 list 来保留它,并使用 for-loop 来处理项目。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-03
相关资源
最近更新 更多