-> for i in range(2, int(math.sqrt(N))):
(Pdb) p sieve
Set([2, 3, 5, 7, 11, 13, 17, 19, 23, 25, 29, 31, 35, 37, 41, 43, 47, 49,
53, 55, 59, 61, 65, 67, 71, 73, 77, 79, 83, 85, 89, 91, 95, 97])
С помощью профайлера разработчики программного обеспечения могут узнать, сколько времени занимает исполнение различных функций и методов.
Продолжая пример с решетом Эратосфена, стоит посмотреть, как тратится процессорное время при вызове функции primes()
:
>>> profile.run("Sieve.primes(100000)")
709 function calls in 1.320 CPU seconds
Ordered by: standard name
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.010 0.010 1.320 1.320 <string>:1(?)
1 0.140 0.140 1.310 1.310 Sieve.py:13(primes)
1 0.000 0.000 1.320 1.320 profile:0(Sieve.primes(100000))
0 0.000 0.000 profile:0(profiler)
65 0.000 0.000 0.000 0.000 sets.py:119(__iter__)
314 0.000 0.000 0.000 0.000 sets.py:292(__contains__)
65 0.000 0.000 0.000 0.000 sets.py:339(_binary_sanity_check)
66 0.630 0.010 0.630 0.010 sets.py:356(_update)
66 0.000 0.000 0.630 0.010 sets.py:425(__init__)
65 0.010 0.000 0.540 0.008 sets.py:489(__isub__)
65 0.530 0.008 0.530 0.008 sets.py:495(difference_update)
Здесь ncalls
— количество вызовов функции или метода, tottime
— полное время выполнения кода функции (без времени нахождения в вызываемых функциях), percall
— тоже, в пересчете на один вызов, cumtime
— аккумулированное время нахождения в функции, вместе со всеми вызываемыми функциями. В последнем столбце приведено имя файла, номер строки с функцией или методов и его имя.
«Странные» имена, например, __iter__
, __contains__
и __isub__
— имена методов, реализующих итерацию по элементам, проверку принадлежности элемента (in
) и операцию -=
. Метод __init__
— конструктор объекта (в данном случае — множества).
При разработке программного обеспечения рекомендуется применять так называемые регрессионные испытания. Для каждого модуля составляется набор тестов, по возможности таким образом, чтобы проверялись не только типичные вычисления, но и «крайние», вырожденные случаи, чтобы испытания затронули каждую ветку алгоритма хотя бы один раз. Тест для данного модуля (написанный сразу после того, как определен интерфейс модуля) находится в файле test_Sieve.py
:
# file: test_Sieve.py
import Sieve, sets
import unittest
class TestSieve(unittest.TestCase):
def setUp(self):
pass
def testone(self):
primes = Sieve.primes(1)
self.assertEqual(primes, sets.Set())
def test100(self):
primes = Sieve.primes(100)
self.assert_(primes == sets.Set([2, 3, 5, 7, 11, 13,
17, 19, 23, 29, 31, 37, 41, 43, 47,
53, 59, 61, 67, 71, 73, 79, 83, 89, 97]))
if __name__ == '__main__':
unittest.main()
Тестовый модуль состоит из определения класса, унаследованного от класса unittest.TestCase
, в котором описывается подготовка к испытаниям (метод setUp
) и сами испытания — методы, начинающиеся на test
. В данном случае таких испытаний всего два: в первом испытывается случай N=1
, а во втором — N=100
.
Запуск тестов производится выполнением функции unittest.main()
. Вот как выглядят успешные испытания:
$ python test_Sieve.py
..
----------------------------------------------------------
Ran 2 tests in 0.002s
OK
В процессе разработки перед каждым выпуском все модули прогоняются через регрессионные испытания, чтобы обнаружить, не были ли внесены ошибки. Однако никакие тесты в общем случае не могут гарантировать безошибочности сложной программы. При дополнении модулей тесты также могут быть дополнены, чтобы отразить изменения в проекте.
Кстати, сам Python и его стандартная библиотека имеют тесты для каждого модуля — они находятся в каталоге test
в месте, где развернуты файлы поставки Python, и являются частью пакета test
.
Успех проекта зависит не только от обеспечения эффективного и качественного кода, но и от качества документации. Утилита pydoc
аналогична команде man
в Unix:
$ pydoc Sieve
Help on module Sieve:
NAME
Sieve — Модуль для вычисления простых чисел от 2 до N
FILE
Sieve.py
FUNCTIONS
primes(N)
Возвращает все простые от 2 до N
Эта страница помощи появилась благодаря тому, что были написаны строки документации — как ко всему модулю, так и к функции primes(N)
.
Стоит попробовать запустить pydoc
следующей командой:
pydoc –p 8088
И направить браузер на URL http://127.0.0.1:8088/ — можно получить документацию по модулям Python в виде красивого web–сайта.
Узнать другие возможности pydoc
можно, подав команду pydoc pydoc
.
Этот пакет и набор утилит пока что не входит в стандартную поставку Python, однако о нем нужно знать тем, кто хочет быстро готовить документацию (руководства пользователя и т.п.) для своих модулей. Этот пакет использует специальный язык разметки (ReStructuredText
), из которого потом легко получается документация в виде HTML, LaTeX и в других форматах. Текст в формате RST легко читать и в исходном виде. С этим инструментом можно познакомиться на http://docutils.sourceforge.net
Данный пакет предоставляет стандартный путь для распространения собственных Python–пакетов. Достаточно написать небольшой конфигурационный файл setup.py
, использующий distutils
, и файл с перечислением файлов проекта MANIFEST.in
, чтобы пользователи пакета смогли его установить командой
python setup.py install
Тонкости работы с distutils
можно изучить по документации.
Взаимодействие с операционной системой
Различные операционные системы имеют свои особенности. Здесь рассматривается основной модуль этой категории, функции которого работают на многих операционных системах.
Разделители каталогов и другие связанные с этим обозначения доступны в виде констант.
Константа | Что обозначает |
---|---|
os.curdir | Текущий каталог |
os.pardir | Родительский каталог |
os.sep | Разделитель элементов пути |
os.altsep | Другой разделитель элементов пути |
os.pathsep | Разделитель путей в списке путей |
os.defpath | Список путей по умолчанию |
os.linesep | Признак окончания строки |
Программа на Python работает в операционной системе в виде отдельного процесса. Функции модуля os
дают доступ к различным значениям, относящимся к процессу и к среде, в которой он исполняется. Одним из важных объектов, доступных из модуля os
, является словарь переменных окружения environ
. Например, с помощью переменных окружения web–сервер передает некоторые параметры в CGI–сценарий. В следующем примере можно получить переменную окружения PATH
:
import os
PATH = os.environ['PATH']
Большая группа функций посвящена работе с файлами и каталогами. Ниже приводятся только те, которые доступны как в Unix, так и в Windows.
access(path, flags) | Проверка доступности файла или каталога с именем path . Режим запрашиваемого доступа указывается значением flags , составленных комбинацией (побитовым ИЛИ) флагов os.F_OK (файл существует), os.R_OK (из файла можно читать), os.W_OK (в файл можно писать) и os.X_OK (файл можно исполнять, каталог можно просматривать). |
chdir(path) | Делает path текущим рабочим каталогом. |
getcwd() | Текущий рабочий каталог. |
chmod(path, mode) | Устанавливает режим доступа к path в значение mode . Режим доступа можно получить, скомбинировав флаги (см. ниже). Следует заметить, что chmod() не дополняет действующий режим, а устанавливает его заново. |
listdir(dir) | Возвращает список файлов в каталоге dir . В список не входят специальные значения "." и ".." . |
mkdir(path[, mode]) | Создает каталог path . По умолчанию режим mode равен 0777 , то есть: S_IRWXU|S_IRWXG|S_IRWXO , если пользоваться константами модуля stat . |
makedirs(path[, mode]) | Аналог mkdir() , создающий все необходимые каталоги, если они не существуют. Возбуждает исключение, когда последний каталог уже существует. |
remove(path) , unlink(path) | Удаляет файл path . Для удаления каталогов используются rmdir() и removedirs() . |
rmdir(path) | Удаляет пустой каталог path . |
removedirs(path) | Удаляет path до первого непустого каталога. В случае если самый последний вложенный подкаталог в указанном пути — не пустой, возбуждается исключение OSError . |
rename(src, dst) | Переименовывает файл или каталог src в dst . |
renames(src, dst) | Аналог rename() , создающий все необходимые каталоги для пути dst и удаляющий пустые каталоги пути src . |
stat(path) | Возвращает информацию о path в виде не менее чем десятиэлементного кортежа. Для доступа к элементам кортежа можно использовать константы из модуля stat , например stat.ST_MTIME (время последней модификации файла). |
utime(path, times) | Устанавливает значения времен последней модификации (mtime ) и доступа к файлу (atime ). Если times равен None, в качестве времен берется текущее время. В других случаях times рассматривается как двухэлементный кортеж (atime , mtime ). Для получения atime и mtime некоторого файла можно использовать stat() совместно с константами модуля stat . |
Для работы с процессами модуль os предлагает следующие функции (здесь упомянуты только некоторые, доступные как в Unix, так и в Windows):
abort() | Вызывает для текущего процесса сигнал SIGABRT . |
system(cmd) | Выполняет командную строку cmd в отдельной оболочке, аналогично вызову system библиотеки языка C. Возвращаемое значение зависит от используемой платформы. |
times() | Возвращает кортеж из пяти элементов, содержащий время в секундах работы процесса, ОС (по обслуживанию процесса), дочерних процессов, ОС для дочерних процессов, а также время от фиксированного момента в прошлом (например, от момента запуска системы). |
getloadavg() | Возвращает кортеж из трех значений, соответствующих занятости процессора за последние 1, 5 и 15 минут. |
В этом модуле описаны константы, которые можно использовать как индексы к кортежам, применяемым функциями os.stat()
и os.chmod()
(а также некоторыми другими). Их можно уточнить в документации по Python.
Программе иногда требуется создать временный файл, который после выполнения некоторых действий больше не нужен. Для этих целей можно использовать функцию TemporaryFile
, которая возвращает файловый объект, готовый к записи и чтению.