Как написать модуль / пакет Python?

Я делал скрипты Python для простых задач на работе и никогда не задумывался о том, чтобы их упаковывать для других. Теперь мне поручено сделать оболочку Python для REST API. Я абсолютно не знаю, с чего начать, и мне нужна помощь.

Что я имею:

(Просто хочу быть как можно более конкретным) У меня есть готовый virtualenv, он также есть в github, также есть файл.gitignore для python, плюс библиотека запросов для взаимодействия с REST API. Вот и все.

Вот текущее дерево каталогов

.
├── bin
│   └── /the usual stuff/
├── include
│   └── /the usual stuff/
├── lib
│   └── python2.7
│       └── /the usual stuff/
├── local
│   └── /the usual stuff/
└── README.md

27 directories, 280 files

Я даже не знаю, где поместить файлы.py, если я когда-либо сделаю один.

Что я хотел сделать:

Сделайте модуль Python доступным для установки с помощью "pip install..."

Если возможно, я хочу пошаговый общий процесс написания модулей Python.

8 ответов

Решение

Модуль - это файл, содержащий определения и операторы Python. Имя файла - это имя модуля с суффиксом .py

Создайте hello.py затем напишите следующую функцию в качестве содержимого:

def helloworld():
   print "hello"

Тогда вы можете импортировать hello:

>>> import hello
>>> hello.helloworld()
'hello'
>>>

Группировать много .py файлы помещают их в папку. Любая папка с __init__.py Python считается модулем, и вы можете назвать их пакетом

|-HelloModule
  |_ __init__.py
  |_ hellomodule.py

Вы можете использовать оператор импорта в вашем модуле обычным способом.

Для получения дополнительной информации см. 6.4. Пакеты

Python 3 - ОБНОВЛЕНО 18 ноября 2015

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

Модуль: Модуль - это файл, содержащий определения и операторы Python. Имя файла - это имя модуля с добавленным суффиксом.py.

Пример модуля: Предположим, у нас есть один скрипт Python в текущем каталоге, здесь я называю его mymodule.py

Файл mymodule.py содержит следующий код:

def myfunc():
    print("Hello!")

Если мы запустим интерпретатор python3 из текущего каталога, мы сможем импортировать и запустить функцию myfunc следующими различными способами (обычно вы просто выбираете один из следующих):

>>> import mymodule
>>> mymodule.myfunc()
Hello!
>>> from mymodule import myfunc
>>> myfunc()
Hello!
>>> from mymodule import *
>>> myfunc()
Hello!

Итак, это было достаточно просто.

Теперь предположим, что вам нужно поместить этот модуль в его собственную выделенную папку, чтобы предоставить пространство имен модуля, вместо того, чтобы просто запускать его ad-hoc из текущего рабочего каталога. Здесь стоит объяснить концепцию упаковки.

Пакет: Пакеты - это способ структурировать пространство имен модуля Python с помощью "точечных имен модулей". Например, имя модуля AB обозначает подмодуль с именем B в пакете с именем A. Точно так же, как использование модулей избавляет авторов различных модулей от необходимости беспокоиться о именах глобальных переменных друг друга, использование названий модулей с точками сохраняет авторов мультимодульных пакетов, таких как NumPy или Python Imaging Library, от необходимости беспокоиться об именах модулей друг друга.

Пример пакета: теперь давайте предположим, что у нас есть следующая папка и файлы. Здесь mymodule.py идентичен ранее, а __init__.py - пустой файл:

.
└── mypackage
    ├── __init__.py
    └── mymodule.py

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

Наш текущий рабочий каталог находится на один уровень выше обычной папки под названием mypackage

$ ls
mypackage

Если мы сейчас запустим интерпретатор python 3, мы сможем импортировать и запустить модуль mymodule.py, содержащий требуемую функцию myfunc, следующими способами (обычно вы просто выбираете один из следующих):

>>> import mypackage
>>> from mypackage import mymodule
>>> mymodule.myfunc()
Hello!
>>> import mypackage.mymodule
>>> mypackage.mymodule.myfunc()
Hello!
>>> from mypackage import mymodule
>>> mymodule.myfunc()
Hello!
>>> from mypackage.mymodule import myfunc
>>> myfunc()
Hello!
>>> from mypackage.mymodule import *
>>> myfunc()
Hello!

Предполагая Python 3, есть отличная документация по адресу: Модули

С точки зрения соглашений об именах для пакетов и модулей, общие рекомендации приведены в PEP-0008 - см. Имена пакетов и модулей.

Модули должны иметь короткие, строчные имена. Подчеркивания могут использоваться в имени модуля, если это улучшает читаемость. Пакеты Python также должны иметь короткие, строчные имена, хотя использование символов подчеркивания не рекомендуется.

Поскольку никто еще не освещал этот вопрос ОП:

Что я хотел сделать:

Сделайте модуль Python доступным для установки с помощью "pip install ..."

Вот абсолютный минимальный пример, показывающий основные этапы подготовки и загрузки вашего пакета в PyPI с использованием setuptools а также twine,

Это ни в коем случае не заменит чтение по крайней мере учебника, это гораздо больше, чем описано в этом очень простом примере.

Создание самого пакета уже описано в других ответах, поэтому давайте предположим, что этот шаг уже пройден и структура нашего проекта выглядит следующим образом:

.
└── hellostackru/
    ├── __init__.py
    └── hellostackru.py

Для того, чтобы использовать setuptools для упаковки нам нужно добавить файл setup.pyэто идет в корневую папку нашего проекта:

.
├── setup.py
└── hellostackru/
    ├── __init__.py
    └── hellostackru.py

Как минимум, мы указываем метаданные для нашего пакета, наш setup.py будет выглядеть так:

from setuptools import setup

setup(
    name='hellostackru',
    version='0.0.1',
    description='a pip-installable package example',
    license='MIT',
    packages=['hellostackru'],
    author='Benjamin Gerfelder',
    author_email='benjamin.gerfelder@gmail.com',
    keywords=['example'],
    url='https://github.com/bgse/hellostackru'
)

Так как мы установили license='MIT'Мы включаем копию в наш проект как LICENCE.txtвместе с файлом readme в reStructuredText как README.rst:

.
├── LICENCE.txt
├── README.rst
├── setup.py
└── hellostackru/
    ├── __init__.py
    └── hellostackru.py

На данный момент, мы готовы начать упаковку, используя setuptools, если у нас его нет, мы можем установить его с pip:

pip install setuptools

Для того, чтобы сделать это и создать source distribution, в корневой папке нашего проекта мы называем наш setup.py из командной строки, указав, что мы хотим sdist:

python setup.py sdist

Это создаст наш дистрибутивный пакет и информацию о яйце, и приведет к структуре папок, подобной этой, с нашим пакетом в dist:

.
├── dist/
├── hellostackru.egg-info/
├── LICENCE.txt
├── README.rst
├── setup.py
└── hellostackru/
    ├── __init__.py
    └── hellostackru.py

На данный момент у нас есть пакет, который мы можем установить, используя pipИтак, из нашего корня проекта (при условии, что у вас есть все имена, как в этом примере):

pip install ./dist/hellostackru-0.0.1.tar.gz

Если все пойдет хорошо, теперь мы можем открыть интерпретатор Python, я бы сказал где-нибудь за пределами каталога нашего проекта, чтобы избежать путаницы, и попытаться использовать наш новый блестящий пакет:

Python 3.5.2 (default, Sep 14 2017, 22:51:06) 
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from hellostackru import hellostackru
>>> hellostackru.greeting()
'Hello Stack Overflow!'

Теперь, когда мы подтвердили, что пакет установлен и работает, мы можем загрузить его в PyPI.

Так как мы не хотим загрязнять живой репозиторий нашими экспериментами, мы создаем учетную запись для тестового репозитория и устанавливаем twine для процесса загрузки:

pip install twine

Теперь мы почти на месте, с нашей учетной записью мы просто говорим twine чтобы загрузить наш пакет, он запросит наши учетные данные и загрузит наш пакет в указанный репозиторий:

twine upload --repository-url https://test.pypi.org/legacy/ dist/*

Теперь мы можем войти в нашу учетную запись в тестовом репозитории PyPI и на некоторое время поразиться нашему недавно загруженному пакету, а затем получить его, используя pip:

pip install --index-url https://test.pypi.org/simple/ hellostackru

Как видим, основной процесс не очень сложен. Как я уже говорил ранее, в этом есть гораздо больше, чем здесь, так что читайте учебник для более подробного объяснения.

После того, как вы определили выбранные вами команды, вы можете просто перетащить сохраненный файл в папку Lib в ваших программных файлах python.

>>> import mymodule 
>>> mymodule.myfunc()

Я создал проект, чтобы легко инициировать скелет проекта с нуля. https://github.com/MacHu-GWU/pygitrepo-project.

И вы можете создать тестовый проект, скажем, learn_creating_py_package,

Вы можете узнать, какой компонент вы должны иметь для различных целей, таких как:

  • создать virtualenv
  • установить себя
  • запустить юнит-тест
  • запуск кода покрытия
  • построить документ
  • развернуть документ
  • запустить unittest в другой версии Python
  • развернуть в PYPI

Преимущество использования pygitrepo является то, что эти утомительные автоматически создаются и адаптируют package_name, project_name, github_account, document host service, windows or macos or linux,

Это хорошее место, чтобы научиться разрабатывать проект на Python, как профессионал.

Надеюсь, это может помочь.

Спасибо.

Создайте файл с именем "hello.py"

Если вы используете Python 2.x

def func():
    print "Hello"

Если вы используете Python 3.x

def func():
    print("Hello")

Запустите файл. Затем вы можете попробовать следующее:

>>> import hello
>>> hello.func()
Hello

Если вы хотите немного сложнее, вы можете использовать следующее:

Если вы используете Python 2.x

def say(text):
    print text

Если вы используете Python 3.x

def say(text):
    print(text)

Смотрите тот, что в скобках рядом с определением? Это важно. Это тот, который вы можете использовать в пределах определения.

Текст - вы можете использовать его, когда хотите, чтобы программа говорила, что вы хотите. По названию это текст. Я надеюсь, что вы знаете, что означает текст. Это означает "слова" или "предложения".

Запустите файл. Затем вы можете попробовать следующее, если вы используете Python 3.x:

>>> import hello
>>> hello.say("hi")
hi
>>> from hello import say
>>> say("test")
test

Для Python 2.x - я думаю, то же самое с Python 3? Без понятия. Поправьте меня, если я допустил ошибку в Python 2.x (я знаю Python 2, но использую Python 3)

Модуль - это файл, содержащий определения и инструкции Python. Имя файла - это имя модуля с расширением.py.

Создайте файл hello.py со следующей функцией в качестве содержимого:

def helloworld():
   print "hello"

Тогда ты можешь

import hello
hello.helloworld()

Чтобы сгруппировать много файлов.py, поместите их в папку. Любая папка с init.py считается python модулем, и вы можете называть их пакетом.

|-HelloModule|_ init.py|_ hellomodule.py

Вы можете создать пакет, который имеет (Пустой файл) и, как показано ниже. *Каждый пакет должен быть пустым в соответствии с тем, что написано в документе « Простой проект» , и вы можете увидеть мой ответ , объясняющий разницу между модулем и пакетом в Python, и вы можете увидеть мой ответ , объясняющий, как создать, загрузить и установить пакет для ТестПиПИ и ПиПИ :

      test
 |-pkg # Here
 |  |-__init__.py
 |  └-file.py
 └-main.py

И,file.pyимеет код ниже:

      # "pkg/file..py"

PI = 3.14

def hello():
    return "Hello"

class Person:
    def __init__(self, name):
        self.name = name

Теперь вы можете импортировать код изpkg/file.pyи используйте его, как показано ниже:

      # "main.py"

from pkg.file import PI, hello, Person

print(PI) # 3.14
print(hello()) # Hello
p = Person("John")
print(p.name) # John

И вpkgпакет, вы создаетеsub_pkgпакет, который имеет__init__.py(пустой файл) и как показано ниже:

      test
 |-pkg
 |  |-__init__.py
 |  |-file.py
 |  └-sub_pkg # Here
 |     |-__init__.py
 |     └-sub_file.py
 └-main.py

И,sub_file.pyимеет код ниже:

      # "pkg/sub_pkg/sub_file.py"

GRAVITY = 9.8

def world():
    return "World"

class Animal:
    def __init__(self, name):
        self.name = name

Теперь вы можете импортировать код изpkg/sub_pkg/sub_file.pyи используйте его, как показано ниже:

      # "main.py"

from pkg.sub_pkg.sub_file import GRAVITY, world, Animal

print(GRAVITY) # 9.8
print(world()) # World
a = Animal("Dog")
print(a.name) # Dog
Другие вопросы по тегам