2015-09-26 13 views
0

我在这里和那里找到了一些答案,但我无法确定构建我想要的东西的确切方法。如果您能提供帮助,请提前致谢。Maya/Python - 通过文本文件循环的函数,但某些行除外

我有多个文本文件,都是以相同的方式构建的,但每个文件都有不同的信息。我想遍历每个文件并逐行返回相应的信息。另一方面,我有一些布尔值,用于定义文件中的某一行是否必须跳过。例如:“如果boolean1为true且lineInTheCorrespondingFile = 40,则跳过该行,否则读取它,但跳过第36和37行而不是”“。

的事情是我不知道如何着手的功能,知道哪些文件被打开该行被读取如果它跳过与否。知道我需要在函数结束时独立返回每一行。

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

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) 

我不知道什么值,我应该进入的功能,使其跳过我想要的线,知道我不能直接写因为每个文件不会在相同的行中断开。 哦,它只返回文件的一行而不是分别。

希望它是明确的,你可以帮助我,再次感谢。

+1

所以你有一个文本文件,你想阅读一些行而不是其他人?你想读的行,你想要从它返回的信息?顺便说一句,使用'eval()'函数应该非常小心。 – enigma

+0

首先,这不是特定于玛雅人的问题,因此如果您只是删除对它的任何引用,则可能会获得更多帮助。只需将'rawFile'作为'locatorsData'的一个参数并切出'cmds'模块调用。 – chadrik

+0

此外,您的数据布局似乎是复杂化的主要来源。你有权控制文件的写入方式吗?你可以使用[json](https://docs.python.org/2/library/json.html)或[pickle](https://docs.python.org/2/library/pickle.html),它支持序列化数据类型,如字典和列表?如果你能提供你需要阅读的文件的前几行的例子,我认为它会有很大的帮助。最后,只要文件不是非常大,将所有数据合并到一个结构中,然后提取所需内容可能更有意义。 – chadrik

回答

0

我看到您的代码有许多问题。

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

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

如果您不能使用发电机,但需要你的函数返回连续行,你需要保存文件迭代器(或者也许是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'd行数据的错误。并且您运行的语句break将导致函数退出而不返回任何内容。如果您只想跳过空白行,则应将检查置于循环的顶部,并使用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语句,而不是象我一样将它们全部整合到一个单独的条件中。

+0

哇!谢谢!这非常有帮助,我用自己的方式重新编写了代码,因为我对python非常陌生,并且一切都很完美! :) – UKDP