Выбор случайного файла из каталога (с большим количеством файлов) в Python

У меня есть каталог с большим количеством файлов (~1mil). Я должен выбрать случайный файл из этого каталога. С тех пор существует столько файлов, os.listdir естественно берет вечность для окончания.

Существует ли способ, которым я могу обойти эту проблему? Возможно, так или иначе узнайте количество файлов в каталоге (не перечисляя его) и выберите 'n'th файл, где n случайным образом сгенерирован?

Файлы в каталоге случайным образом называют.

11
задан NoneType 14 July 2010 в 15:01
поделиться

4 ответа

Я не уверен, что это вообще возможно. Даже на уровне VFS или файловой системы нет гарантии, что подсчет записей в каталоге вообще ведется. Например, многие файловые системы просто записывают суммарный байтовый размер структур записей каталогов, содержащихся в данном каталоге.

Оценку можно сделать, если записи каталога представляют собой структуры фиксированного размера, но сейчас это редкость (рассмотрим LFN для FAT32). Даже если данная файловая система предоставляет подсчет записей без необходимости итерации по каталогу, или если VFS кэширует запись о длине каталога, это, безусловно, зависит от операционной системы, файловой системы и ядра.

1
ответ дан 3 December 2019 в 11:36
поделиться

Вы можете запустить это:

http://mail.python.org/pipermail/python-list/2009-July/1213182.html

И это, вероятно, лучшее возможное решение для вашего проблема, но только там, где n мало - если n становится большим, то os.listdir, вероятно, также подходит для вашей цели.

Я поискал и не нашел другого способа открыть файл в каталоге. Если бы у меня было больше времени, я бы немного поигрался и сгенерировал свои собственные файлы размером ~ 1 миллион.


Я просто придумал другой способ сделать это: Предполагая, что файлы постоянны - вы не получаете ни больше, ни меньше - вы можете сохранить список имен файлов в базе данных sqlite. Тогда было бы относительно просто запросить имя в базе данных по случайному ROWID . Я не знаю, будете ли вы по-прежнему мучиться долгим поиском нужного файла, но, по крайней мере, получение имени файла должно занять немного времени.

Конечно, если файлы в каталоге названы случайным образом, вы можете переименовать файлы (?) И поместить их в структуру каталогов, как предлагает AdamK.

0
ответ дан 3 December 2019 в 11:36
поделиться

Увы, я не думаю, что есть решение вашей проблемы. Во-первых, я не знаю переносимого API, который вернет вам количество записей в каталоге (без их предварительного перечисления). Во-вторых, я не думаю, что есть API, который бы возвращал вам запись в каталоге по номеру, а не по имени.

В общем, программа должна будет перечислить O (n) записей каталога, чтобы получить одну случайную. Тривиальный подход к определению количества записей и последующему выбору одной потребует либо достаточного количества ОЗУ для хранения полного списка ( os.listdir () ), либо потребуется второй раз пронумеровать каталог, чтобы найти случайный (n ) item - всего n + n / 2 операций в среднем.

Есть несколько лучший подход - но лишь немного - см. randomly-selection-lines-from-files . Короче говоря, есть способ выбрать случайный элемент из списка / итератора с неизвестной длиной, читая по одному элементу за раз, и гарантировать, что любой элемент может быть выбран с равной вероятностью. Но это не поможет с os.listdir () , потому что он уже возвращает список в памяти, который уже содержит все 1M + записей - так что вы также можете спросить его о len () ...

3
ответ дан 3 December 2019 в 11:36
поделиться

попробуйте это, (здесь очень быстро с 50К файлами ...)

import glob
import random

list = glob.glob("*/*.*")
print list[random.randrange(0,list.__len__())]
0
ответ дан 3 December 2019 в 11:36
поделиться
Другие вопросы по тегам:

Похожие вопросы: