我需要獲取目錄中的“.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:
我只需要最舊的檔案(如果按創建日期排序,則為第一個),所以也許我不需要對所有檔案進行排序。我可以只挑最老的嗎?
uj5u.com熱心網友回復:
您應該首先檢查相關檔案的創建時間。您可以通過使用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
uj5u.com熱心網友回復:
您可以嘗試使用 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 檔案的示例檔案夾上看到更好的性能。
uj5u.com熱心網友回復:
您可以嘗試以下代碼:
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
此版本可能具有更好的性能,尤其是在大檔案夾上。它在開始時直接使用串列推導來從一開始就忽略不相關的檔案。它使用就地排序。
這樣,此代碼僅使用一個串列。在您的代碼中,您在記憶體中創建了多個串列,并且每次都必須復制資料:
listdir(path)回傳檔案名的初始串列sorted(...)回傳初始串列的過濾和排序副本- return 陳述句之前的串列理解創建另一個新串列
uj5u.com熱心網友回復:
你可以試試這個方法:
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]
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/475905.html
