У меня есть часть кода, который я использую для поиска исполняемых файлов игровых файлов и возвращаю каталоги. Я действительно хотел бы получить своего рода индикатор хода выполнения относительно как далеко вперед os.walk
. Как я выполнил бы такую вещь?
Я пытался делать startpt = root.count(os.sep)
и измеряя прочь этого, но это просто дает как глубоко os.walk
находится в дереве каталогов.
def locate(filelist, root=os.curdir): #Find a list of files, return directories.
for path, dirs, files in os.walk(os.path.abspath(root)):
for filename in returnMatches(filelist, [k.lower() for k in files]):
yield path + "\\"
Я понял это.
Я использовал os.listdir для получения списка каталогов верхнего уровня, а затем использовал функцию .split на пути, который os.walk возвращал, возвращая каталог первого уровня, в котором он находится в данный момент.
Это оставило мне список каталогов верхнего уровня, в котором я мог найти индекс текущей директории os.walk, и сравнить возвращенный индекс с длиной списка, дав мне % полной;)
Это не дает мне гладкого прогресса, потому что уровень работы в каждой директории может варьироваться, но сглаживание индикатора прогресса меня не беспокоит. Но это можно легко сделать, расширив проверку пути глубже в структуру каталога.
Вот последний код из получения моего прогресса:
def locateGameDirs(filelist, root=os.curdir): #Find a list of files, return directories.
toplevel = [folder for folder in os.listdir(root) if os.path.isdir(os.path.join(root, folder))] #List of top-level directories
fileset = set(filelist)
for path, dirs, files in os.walk(os.path.abspath(root)):
curdir = path.split('\\')[1] #The directory os.walk is currently in.
try: #Thrown here because there's a nonexistant(?) first entry.
youarehere = toplevel.index(curdir)
progress = int(((youarehere)/len(toplevel))*100)
except:
pass
for filename in returnMatches(filelist, [k.lower() for k in files]):
yield filename, path + "\\", progress
И прямо сейчас для отладки я делаю это дальше в коде:
for wow in locateGameDirs(["wow.exe", "firefox.exe", "vlc.exe"], "C:\\"):
print wow
Есть ли хороший маленький способ избавиться от этой попытки/исключения?; кажется, первая итерация пути ничего мне не дает...
Сделайте это в двух пропусках: сначала подсчитать, сколько общих файлов / папок на дереве, а затем во время второго прохода делают фактическую обработку.
Вам нужно знать общее количество файлов, чтобы сделать значимый индикатор прогресса.
Вы можете получить количество файлов, как это
len(list(os.walk(os.path.abspath(root))))
, но это займет некоторое время, и вам, вероятно, понадобится индикатор прогресса для этого ...
, чтобы найти количество файлов, которые действительно быстро вам нужна файловая система, которая Отслеживает количество файлов для вас.
Возможно, вы можете сохранить общую сумму от предыдущего запуска и использовать это как оценка
Как я уже сказал в комментарии, Шея бутылочки производительности, скорее всего, лежит за пределами функции функции
. Ваш Returnmatches
- довольно дорогостоящая функция. Я думаю, что вам будет лучше заменять его со следующим кодом:
def locate(filelist, root=os.curdir)
fileset = set(filelist) # if possible, pass the set instead of the list as a first argument
for path, dirs, files in os.walk(os.path.abspath(root)):
if any(file.lower() in fileset for file in files):
yield path + '\\'
таким образом, вы уменьшаете количество расточительных операций, выход один раз за файл в каталоге (который, я думаю, это то, что вы на самом деле имеете взыскание), и вы можете Забудьте о прогрессе одновременно. Я не думаю, что прогресс в любом случае будет ожидаемой особенностью интерфейса.
Просто показать непреодолимый бар прогресса (то есть те, которые показывают BLOB, подпрыгивая назад и вперед или эффект парикмахера). Таким образом, пользователи знают, что программа делает что-то полезное, но не вводить их в заблуждение, что и для завершения и такого.
Можно заменить keyExp
на StringBuilder. перераспределение последовательности в цикле, подобном этому, будет продолжать выделять больше памяти, поскольку последовательности являются неизменяемыми.
StringBuilder keyExp = new StringBuilder();
...
keyExp.Append("|" + readerCSVExp[i - 1]) ;
...
являются ли многие последовательности одинаковыми? вы можете попробовать интернировать их , тогда любые идентичные последовательности будут совместно использовать одну и ту же память, а не быть копиями...
rowExp[fieldCount] = String.Intern(rowNumExp.ToString());
// Dedup Expected
string internedKey = (String.Intern(keyExp.ToString()));
if (!(dictExp.ContainsKey(internedKey)))
{
dictExp.Add(internedKey, rowExp);
}
else
{
listDupExp.Add(rowExp);
}
Я не уверен, как именно работает код, но... кроме того, я бы сказал, что вам не нужно держать rowExp
в словаре, держать что-то еще, как число и записать rowExp
обратно на диск в другом файле. Это, вероятно, сохранит вам больше памяти, так как это, кажется, массив последовательностей из файла, так что, вероятно, большой. Если вы записываете его в файл и сохраняете номер в файле его в, то вы можете вернуться к нему снова в будущем, если вам затем потребуется обработать. Если вы сохранили смещение в файле как значение в словаре, вы сможете быстро найти его снова. Может быть:).
javac -encoding...
); иначе кодирование платформы принято System.out
PrintStream
преобразует ваши последовательности от UTF-16 до байтов в системном кодировании до написания их к Примечания stdout:
-121--251939-Советую избегать обхода каталога. Вместо этого используйте индексированное приложение для быстрого поиска файлов. Интерфейс командной строки приложения можно использовать в подпроцессе и найти файлы практически мгновенно.
В Windows см. Все . В UNIX проверьте местоположение. Не уверен насчет Мака, но я уверен, что там тоже есть вариант.
Сводка «что знать» о кодировании строк на Java:
String
в памяти представляет собой последовательность из 16-разрядных «единиц кода», которые Java обрабатывает как значения char
. Концептуально эти кодовые единицы кодируют последовательность «кодовых точек», где кодовой точкой является «число, приписываемое данному символу согласно стандарту Юникода». Кодовые точки варьируются от 0 до чуть более одного миллиона, хотя до сих пор было определено только 100 тысяч или около того. Кодовые точки от 0 до 65535 кодируются в одну кодовую единицу, в то время как другие кодовые точки используют две кодовые единицы. Этот процесс называется UTF-16 (иначе UCS-2). Существует несколько тонкостей (некоторые кодовые точки являются недействительными, например 65535, и имеется диапазон из 2048 кодовых точек в первом 65536, зарезервированных точно для кодирования других кодовых точек). System.out.println ()
JVM преобразует последовательность в то, для чего эти символы подходят, что часто означает преобразование их в байты с помощью набора символов, который зависит от текущего языка (или того, что JVM угадал из текущего языка). javac
) принимает флаг командной строки ( -кодирование
), который можно использовать для переопределения выбора по умолчанию. Последовательностей
не зависят от какого-либо вида кодирования, если они остаются в ОЗУ,некоторые операции, которые можно выполнить со последовательностями, зависят от языка. Это не вопрос кодирования; но языковой стандарт также определяет «язык», и так бывает, что понятия верхнего и нижнего регистра зависят от используемого языка. Обычный подозреваемый вызывает «unicode». toUpperCase ()
: это дает «UNICODE»
за исключением того, что текущий языковой стандарт является турецким, в этом случае вы получаете «UNİCODE»
(« I
» имеет точку). Основное предположение здесь состоит в том, что если текущий языковой стандарт является турецким, то данные, которыми управляет приложение, вероятно, являются турецким текстом; лично я считаю это предположение в лучшем случае сомнительным. Но так оно и есть. На практике кодировки следует указывать явно в коде, по крайней мере большую часть времени. Не вызывайте String.getBytes ()
, вызовите String.getBytes («UTF-8»)
. Использование кодировки, зависящей от языкового стандарта по умолчанию, хорошо, когда она применяется к некоторым данным, обмениваемым с пользователем, таким как конфигурационный файл или сообщение для немедленного отображения; но в других местах, по возможности, избегайте методов, зависящих от языка.
Среди других языковых компонентов Java имеются календари. Есть весь часовой пояс бизнес, который зависит от «часового пояса», который должен относиться к географическому положению компьютера (а это не часть «языковой» stricto sensu...). Также бесчисленные явские приложения таинственно проваливаются при беге в Бангкоке, потому что на тайском языке Ява по умолчанию соответствует буддийскому календарю, согласно которому текущий год - 2553.
Как правило, предполагайте, что Мир обширен (он есть!) и сохраняйте вещи общие (не делайте ничего, что зависит от шарсета до самого последнего момента, когда необходимо фактически выполнить ввод-вывод).
-121--2251940-Я не связан с атласским ни в каком пути, но я бы честно предложил вам попробовать Dragon Slayer Quest .
Почему?
Поскольку с лицензиями Starter за 60 долларов США вы получите следующие инструменты:
Вам потребуются:
Вы получите:
Так что не ждите, просто идите.
-121--4213491-Ну, это было весело. Вот еще один глупый способ сделать это, но как и все остальное, он только вычисляет правильный прогресс для однородных путей.
import os, sys, time
def calc_progress(progress, root, dirs):
prog_start, prog_end, prog_slice = 0.0, 1.0, 1.0
current_progress = 0.0
parent_path, current_name = os.path.split(root)
data = progress.get(parent_path)
if data:
prog_start, prog_end, subdirs = data
i = subdirs.index(current_name)
prog_slice = (prog_end - prog_start) / len(subdirs)
current_progress = prog_slice * i + prog_start
if i == (len(subdirs) - 1):
del progress[parent_path]
if dirs:
progress[root] = (current_progress, current_progress+prog_slice, dirs)
return current_progress
def walk(start_root):
progress = {}
print 'Starting with {start_root}'.format(**locals())
for root, dirs, files in os.walk(start_root):
print '{0}: {1:%}'.format(root[len(start_root)+1:], calc_progress(progress, root, dirs))
Одна оптимизация, которую вы могли бы сделать - вы конвертируете список файлов в набор при каждом вызове returnMatches, даже если он никогда не изменяется. переместите преобразование в начало функции 'locate' и передавайте набор при каждой итерации.
Думая нестандартно... что если вы сделали это на основе размера:
Thoughts?
-aj
.Это зависит!
Если файлы и каталоги распределены более или менее равномерно, вы можете показать грубый процесс, предположив, что каждый каталог верхнего уровня будет занимать одинаковое количество времени. Но если они распределены неравномерно, дешево об этом не узнать. Вы должны либо заранее приблизительно знать, насколько заполнен каждый каталог, либо вам нужно дважды пройти через os.walk (но это полезно только в том случае, если ваша фактическая обработка занимает намного больше времени, чем сама os.walk).
То есть: скажем, у вас есть 4 каталога верхнего уровня, каждый из которых содержит 4 файла. Если вы предполагаете, что каждый каталог верхнего уровня занимает 25% прогресса, а каждый файл занимает еще 25% прогресса для этого каталога, вы можете показать хороший индикатор прогресса.Но если окажется, что последний подкаталог содержит намного больше файлов, чем первые несколько, ваш индикатор прогресса достигнет 75%, прежде чем вы узнаете об этом. Вы не можете исправить это, если сам файл os.walk является узким местом (а не вашей обработкой) и это произвольное дерево каталогов (не то, где вы заранее знаете, сколько времени займет каждое поддерево).
И, конечно, при условии, что стоимость здесь примерно одинакова для каждого файла ...