繁体   English   中英

如何在Python中获取按创建日期排序的目录中的csv文件列表

[英]How to get the list of csv files in a directory sorted by creation date in Python

我需要获取目录中的“.csv”文件列表,按创建日期排序。

我使用这个功能:

from os import listdir
from os.path import isfile, join, getctime

def get_sort_files(path, file_extension):
    list_of_files = filter(lambda x: isfile(join(path, x)),listdir(path)) 
    list_of_files = sorted(list_of_files, key=lambda x: getctime(join(path, x)))
    list_of_files = [file for file in list_of_files if file.endswith(file_extension)] # keep only csv files
    return list_of_files

当我在包含少量 csv 文件(例如 500 个)的目录中使用它时它工作正常,但是当我在包含 50000 个 csv 文件的目录中使用它时它非常慢:大约需要 50 秒才能返回。

我该如何修改它? 或者我可以使用更好的替代功能吗?

编辑1

瓶颈是sorted功能,所以我必须找到一个替代方法来按创建日期对文件进行排序而不使用它

编辑2

我只需要最旧的文件(如果按创建日期排序,则为第一个),所以也许我不需要对所有文件进行排序。 我可以只挑最老的吗?

您应该首先检查相关文件的创建时间。 您可以通过使用glob()返回感兴趣的文件来做到这一点。

构建 2 元组列表 - 即(创建时间、文件名)

将对每个元组中的第一项(创建日期)隐式执行该列表的排序。

然后,您可以按所需顺序返回文件列表。

from glob import glob
from os.path import join, getctime

def get_sort_files(path, extension):
    list_of_files = []
    for file in glob(join(path,f'*{extension}')):
        list_of_files.append((getctime(file), file))
    return [file for _, file in sorted(list_of_files)]

print(get_sort_files('some directory', 'csv'))

编辑:

我创建了一个包含 50,000 个虚拟 CSV 文件的目录,并对这个答案中显示的代码进行了计时。 耗时 0.24 秒

编辑2:

OP 只想要最旧的文件。 在这种情况下:

def get_oldest_file(path, extension):
    ctime = float('inf')
    old_file = None
    for file in glob(join(path,f'*{extension}')):
        if (ctime_ := getctime(file)) < ctime:
            ctime = ctime_
            old_file = file
    return old_file

你可以试试这个方法:

def get_sort_files(path, extention):
    # Relative path generator
    sort_paths = (join(path, i)
                  for i in listdir(path) if i.endswith(extention))
    sort_paths = sorted(sort_paths, key=getctime)

    return sort_paths
# Include the . char to be explicit
>>> get_sort_files("dir", ".csv")
['dir/new.csv', 'dir/test.csv']

但是,所有文件名都在相对路径中; folder/file.csv 一个效率稍低的解决方法是再次使用lambda键:

def get_sort_files(path, extention):
    # File name generator
    sort_paths = (i for i in listdir(path) if i.endswith(extention))
    sort_paths = sorted(sort_paths, key=lambda x: getctime(join(path, x)))

    return sort_paths
>>> get_sort_files("dir", ".csv")
['new.csv', 'test.csv']

编辑以避免sorted()

使用min()

这是此答案中列出的所有方法中最快的方法

def get_sort_files(path, extention):
    # Relative path generator
    sort_paths = (join(path, i) for i in listdir(path) if i.endswith(extention))
    return min(sort_paths, key=getctime)

手动:

def get_sort_files(path, extention):
    # Relative path generator
    sort_paths = [join(path, i) for i in listdir(path) if i.endswith(extention)]

    oldest = (getctime(sort_paths[0]), sort_paths[0])
    for i in sort_paths[1:]:
        t = getctime(i)
        if t < oldest[0]:
            oldest = (t, i)

    return oldest[1]

您可以尝试以下代码:

def get_sort_files(path, file_extension):
    list_of_files = [file for file in listdir(path) if isfile(join(path, file)) and file.endswith(file_extension)]
    list_of_files.sort(key=lambda x: getctime(join(path, x)))
    return list_of_files

此版本可能具有更好的性能,尤其是在大文件夹上。 它在开始时直接使用列表推导来从一开始就忽略不相关的文件。 它使用就地排序。

这样,此代码仅使用一个列表。 在您的代码中,您在内存中创建了多个列表,并且每次都必须复制数据:

  1. listdir(path)返回文件名的初始列表
  2. sorted(...)返回初始列表的过滤和排序副本
  3. return 语句之前的列表理解创建另一个新列表

您可以尝试使用 os.scandir:

from os import scandir

def get_sort_files(path, file_extension):
    """Return the oldest file in path with correct file extension"""
    list_of_files = [(d.stat().st_ctime, d.path) for d in scandir(path) if d.is_file() and d.path.endswith(file_extension)]
    return min(list_of_files)

os.scandir 似乎对 stat 的调用更少。 有关详细信息,请参阅此帖子 我可以在包含 5000 个 csv 文件的示例文件夹上看到更好的性能。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM