0

我整理了这个脚本来帮助我在特定文件中执行搜索。它做的事情类似于 grep,但我需要比 grep 提供的更具体的东西,所以我正在尝试使用 Python。

我有一堂课,它有三种方法。第二种方法listOccurrencesOfToDoInFile(第 30 行)失败。这是一个小脚本,但由于制表符在 Python 中很重要,因此我将其概括为一个要点,在这里. 谁能告诉我为什么我看似有效的 Python 无效?

import os
import keyword
import sys


class Toodles:

    def walkAndList(directory):
        for dirname, dirnames, filenames in os.walk(directory):

            # print path to all filenames.
            for filename in filenames:
                workingFilename = os.path.join(dirname, filename)
                if(isSourceFile(filename)):
                    listOccurrencesOfToDoInFile(filename)

            # Advanced usage:
            # editing the 'dirnames' list will stop os.walk() from recursing into there.
            if '.git' in dirnames:
                # don't go into any .git directories.
                dirnames.remove('.git')

            for dirs in dirnames:
                self.walkAndList(os.path.join(dirname, dirs)


    #   Find occurences of "todo" and "fixme" in a file
    #   If we find such an occurence, print the filename, 
    #   the line number, and the line itself.
    def listOccurrencesOfToDoInFile(aFileName):
        input = open(aFileName)
        currentLine = 1
        for (line in input):
            line = line.lower()
            currentLine = currentLine + 1
            needle = "todo"
            if (needle in line):
                sys.stdout.write(aFileName + " (" + str(currentLine) + ")" + line)

    #Todo: add a comment
    def isSourceFile(self, name):
        fileName, fileExtension = os.path.splitext(name)
        if (".m" in fileExtension or ".c" in fileExtension or ".h" in fileExtension):
            return True
        return False


if ( __name__ == "__main__") {
    a = Toodles()
    a.walkAndList('.')
}   
4

1 回答 1

3

你错过了一个右括号:

 self.walkAndList(os.path.join(dirname, dirs)

请注意,有两个开头,但只有一个结尾括号。

下一个问题是您正在使用大括号:

if ( __name__ == "__main__") {
    a = Toodles()
    a.walkAndList('.')
}

这是 Python,不是 C、Java 或 Javascript;删除大括号并使用冒号:

if __name__ == "__main__":
    a = Toodles()
    a.walkAndList('.')

for然后,您以一种不合法的 Python 方式在语句中使用括号:

for (line in input):

删除那些括号:

for line in input:

下一个问题是你没有self为你的两个方法定义:

def walkAndList(directory):

def listOccurrencesOfToDoInFile(aFileName):

添加self为第一个参数:

def walkAndList(self, directory):
# ...
def listOccurrencesOfToDoInFile(self, aFileName):

接下来,您将Toodles.isSourceFile()Toodles.listOccurrencesOfToDoInFile()方法视为全局变量,您需要self.在这些前面添加以将它们作为当前实例上的方法调用:

if(isSourceFile(filename)):
    listOccurrencesOfToDoInFile(filename)

应该是(没有多余的括号):

if self.isSourceFile(filename):
    self.listOccurrencesOfToDoInFile(filename)

然后,您可以参考filename您想要的位置(其中缺少路径)workingFilename(包括路径):

self.listOccurrencesOfToDoInFile(workingFilename)

否则打开这些文件会出错。

然后,您的文件扩展名测试存在缺陷;仅用于.endswith()防止匹配文件,例如.csh.h. 而且,没有必要先询问if是否是True,然后单独返回Trueor False您可以直接返回布尔测试:

def isSourceFile(self, name):
    return name.endswith(('.m', '.c', '.h'))

在循环序列时计数时,使用该enumerate()函数为您生成计数器:

for currentLine, line in enumerate(input, 1):
    line = line.lower()

从 1 开始计算行数。

请注意,它os.walk() 已经为您遍历了子目录。没有必要再次递归。通过删除以下行来删除递归:

for dirs in dirnames:
    self.walkAndList(os.path.join(dirname, dirs))

通过一些改进(用于with再次关闭打开的文件、设置在循环needle 之外、提前过滤、使用字符串格式、写出原始行,而不是小写),完整的脚本变为:

import os
import sys


class Toodles(object):
    def walkAndList(self, directory):
        for dirname, dirnames, filenames in os.walk(directory):
            for filename in filenames:
                if self.isSourceFile(filename):
                    workingFilename = os.path.join(dirname, filename)
                    self.listOccurrencesOfToDoInFile(workingFilename)

            # Advanced usage:
            # editing the 'dirnames' list will stop os.walk() from recursing into there.
            if '.git' in dirnames:
                # don't go into any .git directories.
                dirnames.remove('.git')

    #   Find occurences of "todo" and "fixme" in a file
    #   If we find such an occurence, print the filename,
    #   the line number, and the line itself.
    def listOccurrencesOfToDoInFile(self, aFileName):
        needle = "todo"
        with open(aFileName) as input:
            for currentLine, line in enumerate(input, 1):
                if needle in line.lower():
                    sys.stdout.write('{}: ({}){}'.format(aFileName, currentLine, line))

    #Todo: add a comment
    def isSourceFile(self, name):
        return name.endswith(('.m', '.c', '.h'))


if __name__ == "__main__":
    a = Toodles()
    a.walkAndList('.')
于 2013-06-12T15:24:34.987 回答