忽略 StopIteration 错误

3
我刚刚阅读了很多有关如何处理Python中的StopIteration错误的文章,但我仍然无法解决我的特定问题。基本上,我有一个包含许多前缀的csv文件。该文件具有两个带标题的列:Word和Count。Count是该前缀出现的频率。我还有另一个文件,其中包含一些公司名称的列表。前缀文件从公司文件中每个公司名称的第一个单词中获取前缀。我正在尝试去除重复项,现在我想做的是:

每次出现此错误时都忽略StopIteration错误。

换句话说,我只想要一行代码,而不是写下所有被注释掉的“if”语句,该行代码应该是:如果生成StopIteration错误,则通过将有问题的“prefix”视为在前缀文件中出现超过两次的前缀来以某种方式简单地忽略该错误,这样我们应该返回不包括前缀的公司名称的值。我意识到,这忽略了前缀文件中存在不同的前缀值和公司名称的实际前缀之间的事实,但通常这与Python和Excel之间以不同方式存储非美国英语字母以及其他一些看起来不太系统化的方式有关,所以我稍后会手动删除它们。

我的代码是:

def remove_prefix(prefix, first_name):
   #try:
   #EXCEPTIONS:
   #if '(' in prefix:
   #    prefix = prefix[1:]
      #if ')' in prefix:
    #  prefix = prefix[:-1]
    """
      if prefix == "2-10":
        prefix = "2"
      if prefix == "4:2:2":
        prefix = "4"
      if prefix == "5/0" or prefix == "5/7" or prefix == "58921-":
        prefix = "5"
    """
    #except StopIteration:
   #    pass

   print(first_name, prefix)
   input_fields = ('Word', 'Count')
   reader = csv.DictReader(infile1, fieldnames = input_fields)
   #if the prefix has a frequency of x >=2 in the prefix file, then return first_name  without prefix
   #else, return first_Name
   infile1.seek(0)
   #print(infile1.seek(0))
   next(reader)
   first_row = next(reader)
   while prefix != first_row['Word'] and prefix[1:]!= first_row['Word']:
      first_row = next(reader)
      #print(first_name, prefix)
      #print(first_row, first_name, prefix, '\t' + first_row['Word'], prefix[1:])
   if first_row['Count'] >= 2:
      length = len(prefix)
      first_name = first_name[length+1:]
  #print("first name is ", first_name)
  return first_name

2
哪一行代码导致了异常(在回溯中)? - Andy Hayden
感谢您关注此事。该行是“while”语句,因为“prefix”不在first_row ['Word']中,因为它只是略微偏离了。 - user1590499
1
看起来那些 if 语句试图做的事情(对于一些硬编码的特殊情况)是获取字符串开头的数字(在任何其他字符之前停止,比如 /-:)。这可以很容易地通过正则表达式来实现。这样能解决问题吗? - David Robinson
并不完全是这样,因为我只是让那些if语句将前缀变量分配给一个我知道会通过检查的值。我正在寻找的是一种方法,如果前缀变量具有不在first_row ['Word']中的值,则将前缀值分配为可以通过检查的值。 - user1590499
@user1590499:你试过我的建议解决方案了吗? - David Robinson
2个回答

3
我认为这不是你想象中的原因。StopIteration异常是由生成器(reader)读取完所有行时引起的。
例如:
def g():
    "generates 1 (once)"
    yield 1

a = g()
next(a) # is 1
next(a) # StopIteration exception (nothing left to yield)

为了解决这个问题,你可以将next语句放在try, except (pass)语句块中。
while prefix != first_row['Word'] and prefix[1:]!= first_row['Word']:
    try:
        first_row = next(reader)
    except StopIteration:
        pass

然而,正如David指出的那样,这可能不是您处理此事的正确方式。

谢谢,伙计。是的,我尝试了try/except(pass)包装器,但你们说得对,它并没有解决问题的核心。我仍在努力让David的建议适用于我,并且一旦成功,我会在下面发布。感谢您的帮助! - user1590499
不完全是我所需要的,但足够接近,以至于我能够从中汲取灵感并解决我的问题。我正在使用一个生成器来解密排列。每个排列的长度都相同。 - Michael Swartz

2

可以通过先从文件中创建前缀列表,然后对每个前缀使用 startswith 方法来更轻松地完成此操作。例如:

reader = csv.DictReader(infile1)
# # this is assuming there are only two columns in the file: Word and Count
prefixes = [l["Word"] for l in list(reader) if int(l["Count"]) >= 2]

def remove_prefix(first_name):
    for p in prefixes:
        if first_name.startswith(p):
            return first_name[len(p):]
    return first_name

这样做会更简单吗?另一个优点是它只读取文件一次,而不是为了替换每个单词而每次重新打开它。


非常感谢。很抱歉让你等了这么久。当我尝试实现它时,我发现了一堆其他问题(我创建的前缀文件本身有一些错误),所以我陷入了这些问题中几个小时,并希望在解决它后在此发布。我这个周末不会在电脑旁边,但我会确保在星期二得到答案后立即在此发布。再次感谢,我非常感激您的帮助,直观上您的答案非常有道理。我不清楚您定义“前缀”的那行代码如何工作,但总体思路对我来说是有意义的。 - user1590499
嘿,David。抱歉回复晚了。我已经尝试过这个方法,但好像不起作用。更具体地说,你在for循环中分配“前缀”的语句不起作用。当我打印每个前缀时,它每次都会打印“Count”。此外,我必须删除c的int(c)转换,否则会出现错误,所以我需要将c保留为字符串。不确定为什么会这样。非常感谢! - user1590499
谢谢!这个语句的逻辑非常清晰,而且运行得非常好 :) - user1590499

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接