Опубликован: 22.12.2005 | Доступ: свободный | Студентов: 16667 / 511 | Оценка: 4.18 / 3.71 | Длительность: 16:16:00
ISBN: 978-5-9556-0109-0
Лекция 2:

Основные стандартные модули Python

Поддержка цикла разработки

Модули этого раздела помогают поддерживать документацию, производить регрессионное тестирование, отлаживать и профилировать программы на Python, а также обслуживают распространение готовых программ, создавая среду для конфигурирования и установки пакетов.

В качестве иллюстрации можно предположить, что создается модуль для вычисления простых чисел по алгоритму "решето Эратосфена". Модуль будет находиться в файле Sieve.py и состоять из одной функции primes(N), которая в результате своей работы дает все простые (не имеющие натуральных делителей кроме себя и единицы) числа от 2 до N:

import sets
import math
"""Модуль для вычисления простых чисел от 2 до N """
def primes(N):
  """Возвращает все простые от 2 до N"""
  sieve = sets.Set(range(2, N))
  for i in range(2, int(math.sqrt(N)+1)):
    if i in sieve:
      sieve -= sets.Set(range(2*i, N, i))
  return sieve
Модуль pdb

Модуль pdb предоставляет функции отладчика с интерфейсом - командной строкой. Сессия отладки вышеприведенного модуля могла бы быть такой:

>>> import pdb
>>> pdb.runcall(Sieve.primes, 100)
> /home/rnd/workup/intuit-python/examples/Sieve.py(15)primes()
-> sieve = sets.Set(range(2, N))
(Pdb) l
 10     import sets
 11     import math
 12     """Модуль для вычисления простых чисел от 2 до N """
 13     def primes(N):
 14       """Возвращает все простые от 2 до N"""
 15  ->   sieve = sets.Set(range(2, N))
 16       for i in range(2, int(math.sqrt(N)+1)):
 17         if i in sieve:
 18           sieve -= sets.Set(range(2*i, N, i))
 19       return sieve
 20
(Pdb) n
> /home/rnd/workup/intuit-python/examples/Sieve.py(16)primes()
-> for i in range(2, int(math.sqrt(N)+1)):
(Pdb) n
> /home/rnd/workup/intuit-python/examples/Sieve.py(17)primes()
-> if i in sieve:
(Pdb) n
> /home/rnd/workup/intuit-python/examples/Sieve.py(18)primes()
-> sieve -= sets.Set(range(2*i, N, i))
(Pdb) n
> /home/rnd/workup/intuit-python/examples/Sieve.py(16)primes()
-> for i in range(2, int(math.sqrt(N)+1)):
(Pdb) p sieve
Set([2, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39,
41, 43, 45, 47, 49, 51, 53, 55, 57, 59, 61, 63, 65, 67, 69, 71, 73, 75, 77, 79,
81, 83, 85, 87, 89, 91, 93, 95, 97, 99])
(Pdb) n
> /home/rnd/workup/intuit-python/examples/Sieve.py(17)primes()
-> if i in sieve:
(Pdb) n
> /home/rnd/workup/intuit-python/examples/Sieve.py(18)primes()
-> sieve -= sets.Set(range(2*i, N, i))
(Pdb) n
> /home/rnd/workup/intuit-python/examples/Sieve.py(16)primes()
-> for i in range(2, int(math.sqrt(N)+1)):
(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])
Модуль profile

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

Продолжая пример с решетом Эратосфена, стоит посмотреть, как тратится процессорное время при вызове функции 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__ - конструктор объекта (в данном случае - множества).

Модуль unittest

При разработке программного обеспечения рекомендуется применять так называемые регрессионные испытания. Для каждого модуля составляется набор тестов, по возможности таким образом, чтобы проверялись не только типичные вычисления, но и "крайние", вырожденные случаи, чтобы испытания затронули каждую ветку алгоритма хотя бы один раз. Тест для данного модуля (написанный сразу после того, как определен интерфейс модуля) находится в файле 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
..
----------------------------------------------------------------------
Run 2 tests in 0.002s

OK

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

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

Модуль pydoc

Успех проекта зависит не только от обеспечения эффективного и качественного кода, но и от качества документации. Утилита 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.

Пакет docutils

Этот пакет и набор утилит пока что не входит в стандартную поставку Python, однако о нем нужно знать тем, кто хочет быстро готовить документацию (руководства пользователя и т.п.) для своих модулей. Этот пакет использует специальный язык разметки (ReStructuredText), из которого потом легко получается документация в виде HTML, LaTeX и в других форматах. Текст в формате RST легко читать и в исходном виде. С этим инструментом можно познакомиться на http://docutils.sourceforge.net

Пакет distutils

Данный пакет предоставляет стандартный путь для распространения собственных Python-пакетов. Достаточно написать небольшой конфигурационный файл setup.py, использующий distutils, и файл с перечислением файлов проекта MANIFEST.in, чтобы пользователи пакета смогли его установить командой

python setup.py install

Тонкости работы с distutils можно изучить по документации.

Андрей Егоров
Андрей Егоров

def bin(n):

"""Цифры двоичного представления натурального числа """

if n == 0:

   return []

n, d = divmod(n, 2)

return bin(n) + [d]

print bin(69)

Что значит здесь return[] ? Возвращает список? Непонятно какой список? Откуда он? 

 

 

Асмик Гаряка
Асмик Гаряка

Почему при вычислении рейтинга не учитывается уровень, как описано? Для всех курсов У=1, хотя для Специалист должно быть 2.

Александр Воронцов
Александр Воронцов
Украина