优化Python

时间:2017-12-04 16:19:24

标签: python optimization profiling

我有一个包含许多文件夹,文件(.css,.py,.yml等)和代码行的python项目。对于这个项目,我创建了一个名为“统计”的工具,它提供了有关整个项目的信息,例如:

  

全球统计数据:

     

整个项目:: 32329行
  项目主文件(.py,.yml):: 8420行
  没有供应商部分的项目:: 1070行
  核心(src目录):: 394行
  核心与项目主文件相比:: 5%Kraken   框架(vendor / * .py):: 7350行
  主要文件Python代码:: 93%
  供应商Python代码:: 87%
  整个项目规模:: 37M

要获得所有这些数字,我主要使用两个函数:

def count_folder_lines(self, path):
    files = glob.glob(path, recursive=True)
    number = 0
    for file in files:
        num_lines = sum(1 for line in open(file))
        number += num_lines
    return number

def count_number_of_files(self, path):
    files = glob.glob(path, recursive=True)
    return len(files)

第一个用于计算文件夹中的行数,第二个用于计算特定文件的数量(例如:src / * .py)。 但要获得项目的统计数据,需要4.9到5.3秒,这很多。

有没有办法让它更快?并行编程或使用Cython会改变什么吗?

祝你有愉快的一天, 谢谢。

1 个答案:

答案 0 :(得分:0)

最后为我找到了最有效的解决方案: 我正在使用多处理模块来并行计算每个文件的行数。

def count_folder_lines(self, path):
    """ 
        Use a buffer to count the number of line of each file among path.
        :param path: string pattern of a file type
        :return: number of lines in matching files
    """
    files = glob.glob(path, recursive=True)
    number = 0
    for file in files:
        f = open(file, 'rb')
        bufgen = takewhile(lambda x: x,
                           (f.raw.read(1024 * 1024) for _ in repeat(None)))
        number += sum(buf.count(b'\n') for buf in bufgen if buf)
    return number

def count_number_of_files(self, path):
    """
        Count number of files for a string pattern
        :param path: files string pattern
        :return: number of files matching the pattern
    """
    files = glob.glob(path, recursive=True)
    return len(files)

def multiproc(self):
    """
        Multiprocessing to launch several processes to count number of
        lines of each string pattern in self.files
        :return: List of number of files per string pattern
                    (list of int).
    """
    pool = mp.Pool()
    asyncResult = pool.map_async(self.count_folder_lines, self.files)
    return asyncResult.get()

使用此解决方案,计数需要大约1.2秒,而之前需要大约5秒。

祝你有个美好的一天!