Как написать модуль / пакет 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
Вы можете использовать оператор импорта в вашем модуле обычным способом.
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