Я пытаюсь написать код, который должен искать на ноутбуке файл, открывать его, если он найден, и читать контекст этого файла (это должен быть .txt или .doc). Пока что я написал этот код, который работает:
def search(drive, target):
file_path=""
if drive == "D":
for root, dirs, files in os.walk(r"D:\"):
for name in files:
if name == target:
file_path = os.path.abspath(os.path.join(root, name))
elif drive == "C":
for root, dirs, files in os.walk(r"C:\"):
for name in files:
if name == target:
file_path = os.path.abspath(os.path.join(root, name))
return file_path
def path():
file_name = input("Enter the name of the desired file: ")
path = os.path.abspath(file_name)
file_path = search(path[0], file_name)
return file_path
Проблема в том, что этот фрагмент кода очень медленный, так как он должен просматривать каждый каталог на диске (единственный трюк, который я использовал, чтобы сэкономить время, — это взять abspath и посмотреть, на каком диске он сохранен, поэтому он не смотрит на каждый существующий диск).
Я подумываю использовать многопроцессорность, но не знаю, как ее использовать. Кто-нибудь может помочь? Большое спасибо за уделенное время!
1 ответ
Поскольку вам уже требуется, чтобы имя файла начиналось с правильного имени диска, ваш target
уже будет выглядеть как нормальный действительный путь. Таким образом, вы можете по крайней мере проверить, действительно ли введенный пользователем путь является правильным, сократив весь поиск:
def search(drive, target):
if os.path.isfile(target):
return os.path.abspath(target)
...
Вам также следует прекратить поиск, как только вы найдете свою цель, и использовать in
ключевое слово вместо того, чтобы вручную проверять все файлы самостоятельно:
...
for root, dirs, files in os.walk(r"D:\"):
if target in files:
return os.path.abspath(os.path.join(root, target))
В остальном, боюсь, вам в основном не повезло. Есть только два способа быстро что-то найти в большой куче вещей:
- Вы просматриваете все, пока не найдете то, что ищете.
- У вас есть структура данных, называемая индексом, которая сообщает вам, как найти каждое (или, по крайней мере, некоторые, включая, надеюсь, то, что вы ищете) что-то.
В мире Unix есть инструмент командной строки locate
, который использует периодически обновляемую базу данных файлов, чтобы ускорить поиск файлов (пока они находятся в этой базе данных). Я не уверен, что такое эквивалентный инструмент Windows (командная строка), но вы можете найти какое-то решение Вот. Затем вы можете вызвать этот инструмент, используя subprocess
.
С вашей стороны, если вам нужен этот поиск очень часто (дважды, вероятно, уже достаточно часто), вы также можете создать такой индекс самостоятельно, то есть вам нужно проверить все файлы только один раз:
from collections import defaultdict
INDEX = {}
def build_index(drive):
index = defaultdict(set)
for root, _, files in os.walk(drive):
for file in files:
index[file].add(root)
return dict(index)
def search(drive, target):
if drive not in INDEX:
INDEX[drive] = build_index(drive)
root = next(iter(INDEX[drive][target]))
return os.path.abspath(os.path.join(root, target))
Не то чтобы это произвольно выбирает один результат, если имя файла появляется несколько раз, аналогично вашему коду, который выбирает последнее встреченное (с произвольно определенным порядком обработки). На моей машине, например, есть 8708 файлов с именами index.js
и непонятно какой ты хочешь. Возможно, лучше было бы вернуть их все вместо одного произвольного.
Отличный код! Я не думал об этом подходе! Я использовал вашу идею, и она идеально вписывается в мой код! Большое спасибо за ваш любезный ответ! Я немного изменил его в том смысле, что после завершения функции поиска результат будет сохранен в репозитории, откуда мой код может отслеживать каждый файл, к которому нужно было получить доступ хотя бы один раз. Большое спасибо! Всего наилучшего!
— tudor.il
locate
… Я не уверен, что такое эквивалентный инструмент Windows (командная строка) …where
довольно быстро.— подтверждение