Maya/Python - 循环遍历文本文件的函数,除了某些行

Maya/Python - function which loops though text file except for some lines

我在这里和那里找到了一些答案,但我想不出构建我想要的东西的确切方法。如果您能提供帮助,请提前致谢。

我有多个文本文件,它们都是以相同的方式构建的,但每个文件中的信息不同。我想遍历每个文件并逐行 return 其中的信息。另一方面,我有一些布尔值定义是否必须跳过文件中的特定行。例如:"if boolean1 is true and lineInTheCorrespondingFile = 40, then skip that line, else, read it but skip line 36 and 37 instead".

问题是我不知道如何进行,因为函数知道打开了哪个文件 and 读取了哪一行 and如果它必须跳过它或不。知道我需要在函数末尾 return 独立编辑每一行。

到目前为止,这是我的代码:

def locatorsDatas (self):

    preset = cmds.optionMenu ("presetMenu", q = 1, v = 1)
    rawFile = presetsDir + preset.lower() + ".txt"

    with open(rawFile) as file:
        file.seek (0)
        for lineNum, line in enumerate(file, start = 1):
            if lineNum > 8 : # Skip header
                locator = eval (line)
                locName = locator[0]
                xVal = locator[1]
                yVal = locator[2]
                zVal = locator[3]
                locScale = locator[4]
                locColor = locator[5]
                if locator == "":
                    break

                return (locName, xVal, yVal, zVal, locScale, locColor)

我不知道我应该将什么值传递给函数以使其跳过我想要的行,因为我知道我不能将它直接写入其中,因为每个文件都不会在同一行中断。 哦,它只有 return 文件的一行而不是每一行。

希望说清楚了,能帮帮我,再次感谢。

我发现你的代码有很多问题。

首先,您总是return处理第 8 行的数据,而不是任何其他数据。如果您有许多要从文件中提取的值,您可能希望使用 yield 语句而不是 return 使您的函数成为生成器。然后调用代码可以使用 for 循环访问数据或将生成器传递给 list 或接受任何可迭代的另一个函数。

def locatorsDatas(self):
    # ...
    lineNum, line in enumerate(file, start=1):
        # ...
        yield results

如果你不能使用生成器但需要你的函数来 return 连续的行,你需要将文件迭代器(或者也许 enumerate 环绕它的迭代器)保存在某处在函数范围之外。这意味着您不需要在每次调用该函数时都重新打开文件。你可以这样做:

def __init__(self):
    preset = cmds.optionMenu ("presetMenu", q = 1, v = 1)
    rawFile = presetsDir + preset.lower() + ".txt"
    self.preset_file_enumerator = enumerate(open(rawFile)) # save the iterator on self

def locatorsDatas(self):
    try:
        lineNum, line = next(self.preset_file_enumerator) # get a value from the iterator
        # do your processing
        return results
    except StopIteration:
        # do whatever is appropriate when there's no more data in the file here
        raise ValueError("no more data") # such as raising an exception

我看到的下一个问题是如何处理每一行以获取单独的数据。你正在使用 eval 如果你正在处理的数据被轻微委托的话,这是一个非常糟糕的主意。那是因为 eval 将其参数解释为 Python 代码。它可以任何事情,包括从您的硬盘中删除文件!更安全的版本是 ast.literal_eval,它只允许字符串包含 Python 文字(包括列表、字典和集合,但不包括变量查找、函数调用或其他更复杂的代码)。

你还有一个错误检查,我认为它不会按照你的意图进行。 if locator == "" 测试可能放置得太晚,以避免前面的行从 eval 行提取数据时出错。而 break 声明 运行 将导致函数退出,而不会再 returning 任何东西。如果你只是想跳过空行,你应该把检查放在循环的顶部并使用 continue 而不是 break.

现在我们终于可以解决您在问题标题中提出的问题。如果您想根据各种标志跳过某些行,您只需要在循环时检查这些标志并执行 continue 以跳过您不想阅读的行。我不完全理解你问的关于如何传递标志的问题,但假设你可以将它们作为参数提供,下面是代码的外观草图:

def locatorsDatas(self, skip_40=False, skip_50=True):
    # open file, ...
    for lineNum, line in enumerate(file, start = 1):
        if  (not line or
             lineNum < 8 or
             skip_40 and lineNum == 40 or
             skip_50 and lineNum == 50):
            continue
        # parse the line
        yield result

显然,您应该使用自己的标志名称和逻辑,而不是我为示例代码编写的名称和逻辑。如果您的逻辑更复杂,您可能更喜欢为每个标志使用单独的 if 语句,而不是像我那样将它们全部打包到一个单独的条件中。