Сканирование всего компьютера

skanirovanie vsego kompjutera Законченные системные программы

Наконец, несмотря на то, что путь поиска модулей обычно включает все исходные файлы Python, доступные для импортирования на вашем компьютере, тем не менее и этот ответ может оказаться неполным. С технической точки зрения, эта версия проверяет только модули — файлы с исходным программным кодом на языке Python, которые запускаются как самостоятельные сценарии, могут не включаться в путь поиска модулей. Кроме того, путь поиска модулей в некоторых сценариях может изменяться вручную прямо во время выполнения (например, прямым изменением списка sys.path в сценариях, выполняющихся на веб-сервере), чтобы включить в него дополнительные каталоги, которые недоступны для сценария в примере 6.3.

В конечном счете, чтобы отыскать наибольший исходный файл на компьютере, необходимо просканировать весь жесткий диск; эта возможность почти полностью поддерживается сценарием в примере 6.2. Нам нужно лишь передать ему в аргументе имя корневого каталога и добавить в него некоторые улучшения из версии, сканирующей путь поиска модулей (позволяющие избежать повторного сканирования одних и тех же каталогов в случае поиска по всему компьютеру, пропускать ошибки и подсчитывать строки, если нам не жалко на это времени). В примере 6.4 приводится реализация такого универсального сценария
сканирования дерева каталогов, снабженного усовершенствованиями, необходимыми для сканирования всего диска.

Пример 6.4. PP4E\System\Filetools\bigext-tree.py

Отыскивает наибольший файл заданного типа в произвольном дереве каталогов. Пропускает каталоги, которые уже были просканированы; перехватывает ошибки; добавляет возможность вывода трассировки поиска и подсчета строк.

Кроме того, использует множества, итераторы файлов и генераторы, чтобы избежать загрузки содержимого файлов целиком, и пытается обойти проблемы, возникающие при выводе недекодируемых имен файлов/каталогов.

import os, pprint

from sys import argv, exc_info

trace = 1 # 0=выкл., 1=каталоги, 2=+файлы

dirname, extname = os.curdir, ‘.py’ # по умолчанию файлы .py в cwd

if len(argv) > 1: dirname = argv[1] # например: C:\, C:\Python31\Lib

if len(argv) > 2: extname = argv[2] # например: .pyw, .txt

if len(argv) > 3: trace = int(argv[3]) # например: “. .py 2”

подпись: def tryprint(arg):
try:
print(arg)
except unicodeencodeerror:
print(arg.encode())
подпись: # непечатаемое имя файла?
# вывести как строку байтов


visited = set()

allsizes = []

for (thisDir, subsHere, filesHere) in os.walk(dirname):

if trace: tryprint(thisDir)

thisDir = os.path.normpath(thisDir)

fixname = os.path.normcase(thisDir) if fixname in visited:

if trace: tryprint(‘skipping ‘ + thisDir) else:

visited.add(fixname)

for filename in filesHere:

if filename.endswith(extname):

if trace > 1: tryprint(‘+++’ + filename)

fullname = os.path.join(thisDir, filename) try:

bytesize = os.path.getsize(fullname)

linesize = sum(+1 for line in open(fullname, ‘rb’)) except Exception:

print(‘error’, exc_info()[0])

else:

allsizes.append((bytesize, linesize, fullname))

for (title, key) in [(‘bytes’, 0), (‘lines’, 1)]:

print(‘\nBy %s…’ % title)

allsizes.sort(key=lambda x: x[key])

pprint.pprint(allsizes[:3])

pprint.pprint(allsizes[-3:])

В отличие от предыдущей версии, эта позволяет выполнять поиск файлов с определенными расширениями и в определенных каталогах. По умолчанию производится поиск файлов Python в текущем рабочем каталоге:

C:\\PP4E\System\Filetools> bigext-tree.py

By bytes

[(21, 1, ‘.\\__init__.py’),

(461, 17, ‘.\\bigpy-dir.py’),

(818, 25, ‘.\\bigpy-tree.py’)]

[(1696, 48, ‘.\\join.py’),

(1940, 49, ‘.\\bigext-tree.py’),

(2547, 57, ‘.\\split.py’)]

By lines

[(21, 1, ‘.\\__init__.py’),

(461, 17, ‘.\\bigpy-dir.py’),

(818, 25, ‘.\\bigpy-tree.py’)]

[(1696, 48, ‘.\\join.py’),

(1940, 49, ‘.\\bigext-tree.py’),

(2547, 57, ‘.\\split.py’)]

Настраивая работу сценария, можно задать имя каталога, расширение искомых файлов и уровень подробности вывода трассировочной информации (уровень 0 запрещает трассировку, при уровне 1 (по умолчанию) выводятся имена сканируемых каталогов):

C:\\PP4E\System\Filetools> bigext-tree.py .. .py 0

By bytes

[(21, 1, ‘..\\__init__.py’),

(21, 1, ‘..\\Filetools\\__init__.py’),

(28, 1, ‘..\\Streams\\hello-out.py’)]

[(2278, 67, ‘..\\Processes\\multi2.py’),

(2547, 57, ‘..\\Filetools\\split.py’),

(4361, 105, ‘..\\Tester\\tester.py’)]

By lines

[(21, 1, ‘..\\__init__.py’),

(21, 1, ‘..\\Filetools\\__init__.py’),

(28, 1, ‘..\\Streams\\hello-out.py’)]

[(2547, 57, ‘..\\Filetools\\split.py’),

(2278, 67, ‘..\\Processes\\multi2.py’),

(4361, 105, ‘..\\Tester\\tester.py’)]

Кроме того, этот сценарий поволяет выполнять поиск файлов разных типов. Ниже приводятся результаты поиска наибольшего и наименьшего текстового файла, начиная с каталога уровнем выше текущего (эти результаты имели место на тот момент времени, когда я запускал сценарий):

C:\\PP4E\System\Filetools> bigext-tree.py .. .txt 1

..

..\Environment

..\Filetools

..\Processes

..\Streams

..\Tester

..\Tester\Args

..\Tester\Errors

..\Tester\Inputs

..\Tester\Outputs

..\Tester\Scripts

..\Tester\xxold

..\Threads

By bytes

[(4, 2, ‘..\\Streams\\input.txt’),

(13, 1, ‘..\\Streams\\hello-in.txt’),

(20, 4, ‘..\\Streams\\data.txt’)]

[(104, 4, ‘..\\Streams\\output.txt’),

(172, 3, ‘..\\Tester\\xxold\\README.txt.txt’),

(435, 4, ‘..\\Filetools\\temp.txt’)]

By lines

[(13, 1, ‘..\\Streams\\hello-in.txt’),

(22, 1, ‘..\\spam.txt’),

(4, 2, ‘..\\Streams\\input.txt’)]

[(20, 4, ‘..\\Streams\\data.txt’),

(104, 4, ‘..\\Streams\\output.txt’),

(435, 4, ‘..\\Filetools\\temp.txt’)]

А чтобы выполнить поиск по всей системе, достаточно просто передать сценарию имя корневого каталога (в Unix-подобных системах вместо C:\ используйте /) и расширение файлов (по умолчанию используется расширение .py). Итак, победитель… (только не заключайте никакие пари):

C:\\PP4E\dev\Examples\PP4E\System\Filetools> bigexttree.py C:\

C:\

C:\$Recycle.Bin

C:\$Recycle.Bin\S-1-5-21-3951091421-2436271001-910485044-1004

C:\cygwin

C:\cygwin\bin

C:\cygwin\cygdrive

C:\cygwin\dev

C:\cygwin\dev\mqueue

C:\cygwin\dev\shm

C:\cygwin\etc

…МНОГО строк опущено…

By bytes

[(0, 0, ‘C:\\cygwin\\\\python31\\Python-3.1.1\\Lib\\build_class.py’), (0, 0, ‘C:\\cygwin\\\\python31\\Python-3.1.1\\Lib\\email\\mime\\__init__.

py’),

(0, 0, ‘C:\\cygwin\\\\python31\\Python-3.1.1\\Lib\\email\\test\\__init__. py’)]

[(380582, 78, ‘C:\\Python31\\Lib\\pydoc_data\\topics.py’),

(398157, 83, ‘C:\\\\Install\\Source\\Python-2.6\\Lib\\pydoc_topics.py’), (412434, 83, ‘C:\\Python26\\Lib\\pydoc_topics.py’)]

By lines

[(0, 0, ‘C:\\cygwin\\\\python31\\Python-3.1.1\\Lib\\build_class.py’), (0, 0, ‘C:\\cygwin\\\\python31\\Python-3.1.1\\Lib\\email\\mime\\__init__.

py’),

(0, 0, ‘C:\\cygwin\\\\python31\\Python-3.1.1\\Lib\\email\\test\\__init__. py’)]

[(204107, 5589, ‘C:\\\Install\\Source\\Python-3.0\\Lib\\decimal.py’), (205470, 5768, ‘C:\\cygwin\\\\python31\\Python-3.1.1\\Lib\\decimal.py’), (211238, 5768, ‘C:\\Python31\\Lib\\decimal.py’)]

Логика трассировки построена так, что позволяет следить за тем, как выполняется обход каталогов. Я сократил список каталогов в этом примере, чтобы не перегружать его лишней информацией (и уместить на страницу). Для выполнения этой команды может потребоваться достаточно продолжительное время. На моем нетбуке, работающем, как это ни печально, под управлением Windows 7, потребовалось 11 минут, чтобы просканировать жесткий диск, содержащий примерно 59 Гбайт данных, 200K файлов и 25K каталогов, при невысокой нагрузке на систему (8 минут — при отключенной трассировке, и полчаса, когда было запущено множество других приложений). Однако этот сценарий дает самый исчерпывающий ответ на поставленный вопрос.

Это решение настолько полное, насколько позволяет пространство в книге. Ради интереса подумайте о возможности сканирования нескольких дисков; о том, что исходные файлы Python могут находиться в zip-архивах, как в пути поиска модулей, так и за его пределами (os. walk просто игнорирует zip-файлы в примере 6.3). Кроме того, файлы с исходными текстами могут иметь разные расширения — файлы с расширением .pyw подавляют вывод окна консоли в Windows, а файлы сценариев верхнего уровня могут иметь произвольные расширения. Фактически имена файлов сценариев верхнего уровня вообще могут не иметь расширения и при этом оставаться файлами с исходными текстами на языке Python. Кроме того, некоторые модули, доступные для импортирования, не являясь файлами с исходными текстами на языке Python, могут присутствовать в формате скомпилированных двоичных файлов или быть статически связаны с выполняемым файлом интерпретатора Python. В интересах экономии места мы оставим эти варианты (довольно сложные в реализации!) расширения процедуры поиска, как упражнение для самостоятельного решения.

Использованная литература:
Марк Лутц — Программирование на Python, 4-е издание, I том, 2011

Каталог сайтов Всего.ру
Оцените статью
Секреты программирования
Добавить комментарий