понедельник, 9 июля 2012 г.

Python 201: Создание модулей и пакетов (Перевод)


Создание модулей на Python - это то, что большинство программистов делают каждый день. Каждый раз, когда Вы создаёте скрипт - Вы создаёте новый модуль. Вы можете импортировать ваш модуль в другие модули. Пакет - это набор модулей. То, что Вы импортируете в ваши скрипты из стандартной библиотеки - это тоже модули или пакеты. В этой статье мы посмотрим на то, как создаются модули и пакеты, но больше времени потратим именно на пакеты, так как они чуть сложнее.

Как создать модуль на Python
Мы начнём с создания очень простого модуля. Этот модуль предоставит нам доступ к простейшим арифметическим операциям без какой-либо обработки ошибок. Вот наш первый пример:
#----------------------------------------------------------------------
def add(x, y):
    """"""
    return x + y
 
#----------------------------------------------------------------------
def division(x, y):
    """"""
    return x / y
 
#----------------------------------------------------------------------
def multiply(x, y):
    """"""
    return x * y
 
#----------------------------------------------------------------------
def subtract(x, y):
    """"""
    return x - y
У этого кода, конечно, есть свои недостатки. В частности, если Вы передаёте два integer в метод division, то и обратно Вы получите integer (в Python 2.x), что, может быть, не совсем то, что Вы ожидаете. Кроме того, нет никакой проверки деления на ноль или того, что аргументами являются именно числа, а не строки. Но не в этом суть. Суть в том, что как только Вы сохранили этот код, Вы получили модуль. Давайте назовём его arithmetic.py. Что теперь с ним можно делать? Вы можете импортировать его и использовать любую из определённых в нём функций. Более того, мы можем даже сделать его исполняемым! Давайте попробуем!
Во первых, мы напишем небольшой скрипт, который импортирует этот модуль и использует его функции:
import arithmetic
 
print arithmetic.add(5, 8)
print arithmetic.subtract(10, 5)
print arithmetic.division(2, 7)
print arithmetic.multiply(12, 6)
Теперь давайте немного изменим оригинальный скрипт так, чтобы мы смогли запускать его из командной строки:
#----------------------------------------------------------------------
def add(x, y):
    """"""
    return x + y
 
#----------------------------------------------------------------------
def division(x, y):
    """"""
    return x / y
 
#----------------------------------------------------------------------
def multiply(x, y):
    """"""
    return x * y
 
#----------------------------------------------------------------------
def subtract(x, y):
    """"""
    return x - y
 
#----------------------------------------------------------------------
if __name__ == "__main__":
    import sys
    print sys.argv
    v = sys.argv[1].lower()
    valOne = int(sys.argv[2])
    valTwo = int(sys.argv[3])
    if v == "a":
        print add(valOne, valTwo)
    elif v == "d":
        print division(valOne, valTwo)
    elif v == "m":
        print multiply(valOne, valTwo)
    elif v == "s":
        print subtract(valOne, valTwo)
    else:
        pass
Правильнее было бы конечно использовать модули optparse или argparse. Можете попробовать сделать это сами, а мы перейдём к пакетам!

Как создать пакет для Python

Основная разница между модулем и пакетом в том, что пакет - это коллекция модулей И он содержит файл  __init__.py. В зависимости от сложности пакета, может быть даже не один файл __init__.py. Давайте посмотрим на структуру папки пакета, чтобы это стало чуть более понятно, а затем уже будем писать соответствующий код:
myMath/
    __init__.py
    adv/
        __init__.py
        sqrt.py
        fib.py
    add.py
    subtract.py
    multiply.py
    divide.py
Теперь нам остаётся только воспроизвести эту структуру на практике. Создадим каждый из этих файлов в соответствующей папке с соответствующим именем. Для файлов add, subtract, multiply и divide Вы можете использовать те функции, которые мы уже создали. А вот код оставшихся двух функций (для чисел фибоначи мы используем этот код с  StackOverflow:):
# fib.py
from math import sqrt
 
#----------------------------------------------------------------------
def fibonacci(n):
    """

http://stackoverflow.com/questions/494594/how-to-write-the-fibonacci-sequence-in-python

    """
    return ((1+sqrt(5))**n-(1-sqrt(5))**n)/(2**n*sqrt(5))
Вот код для файла sqrt.py:
# sqrt.py
import math
 
#----------------------------------------------------------------------
def squareroot(n):
    """"""
    return math.sqrt(n)
Оба файла  __init__.py можно оставить пустыми, но в таком случае Вам придётся при импортировании писать что-то вроде mymath.add.add(x,y), что, несомненно, неудобно, поэтому мы добавим во внешний __init__.py такой код:
# outer __init__.py
from add import add
from divide import division
from multiply import multiply
from subtract import subtract
from adv.fib import fibonacci
from adv.sqrt import squareroot
Теперь, для того, чтобы иметь возможность импортировать этот модуль, мы должны добавить его в наш Python path. Вы можете просто скопировать эту папку в site-packages. В Windows она обычно находится по адресу C:\Python26\Lib\site-packages. Или же, Вы можете в самом скрипте, где Вы хотите использовать ваш пакет, просто изменить путь поиска модулей:
import sys
 
sys.path.append('C:\Users\mdriscoll\Documents')
 
import mymath
 
print mymath.add(4,5)
print mymath.division(4, 2)
print mymath.multiply(10, 5)
print mymath.fibonacci(8)
print mymath.squareroot(48)
Обратите внимание, что саму папку mymath я не добавляю в путь. Вам надо добавить папку, содержащую папку с модулем, а не саму папку с модулем. Вот и всё - наш первый пакет готов!

Домашнее чтение

Исходники

5 комментариев:

  1. Спасибо за перевод, очень доступно!!

    ОтветитьУдалить
  2. Теперь давайте немного изменим оригинальный скрипт так, чтобы мы смогли запускать его из командной строки:

    и как его запускать??

    ОтветитьУдалить
    Ответы
    1. смотря в какой системе. В windows: С:\python32\python.exe script.py, в *nix - сделать исполняемым и добавить путь к интрепретатору в начале. (пути и имя скрипта даны для примера)

      Удалить
  3. Я не совсем понял как обойтись без импортов __init__.py. Примером я не хочу их писать и запускать функции как mymath.add.add(x,y). Но оставив __init__.py пустым - у меня ничего не получается:

    >>> import mymath
    >>>
    >>> mymath.add.add(5,4)
    Traceback (most recent call last):
    File "", line 1, in
    AttributeError: 'module' object has no attribute 'add'
    >>>


    C импортом в __init__.py - все гуд

    ОтветитьУдалить