In order to distribute a Python application, you need to create a Python package by wrapping project directory with some additional files, specifing related elements e.g. resources, dependencies and finally releasing it.
Creating a Python Package
This is an example of a Pyhon package distribution file (named: setup.py).
from setuptools import setup
setup(
name = 'zaiste',
version = '0.1.0',
description = 'A Python package example',
author = 'Zaiste',
long_description=open("README.txt").read(),
author_email = '[email protected]',
url = 'https://github.com/zaiste/zaiste-py',
packages=['zaiste'],
include_package_data=True,
install_requires=[
# list of this package dependencies
],
entry_points={
'console_scripts': ['zaiste-cli=zaiste.cli:main'],
}
)In order to facilitate the tasks of distribution, Python distribution utilities
toolset distutils was created by the Python core team. It is, however,
preferable to use a 3rd party setuptools instead.
If you need to add extra non-Python files and directories e.g. static files or
templates, you must explicitly specify them in the manifest file (MANIFEST.in)
to be packaged along with adding include_package_data=True to the setup()
function.
include README.rst
include docs/*.md
recursive-include templates *
recursive-include static *Additionally, you can use packages that are properly arranged using setuptools,
but aren’t published to PyPI; dependency_links= option is used for that:
setup(
...
dependency_links=['http://github.com/zaiste/zaiste-py/tarball/master#egg=package-2.0']
...
)You can now create a Python package for this project
python setup.py sdistand install it locally
pip install .The command above is similar to python setup.py install but:
- it automatically downloads all dependencies
- you can easily uninstall and update packages with a single command
pipwill automatically search the Python Package Index (PyPi)pipis bundled with Python (as of Python 2.7.9 / Python 3.4.0)
or install the package with a symlink (changes to the source files will be immediately available to other users of the package)
pip install -e .Python package (and module) names should be in lowercase, unique on PyPI, with
no hyphens (-) and prefereably no underscore (_) signs
zaiste/
zaiste/
__init__.py
setup.pyAdding tests
Create a tests directory inside your module
zaiste/
zaiste/
__init__.py
tests/
__init__.py
test_zaiste.py
setup.pyand use unittest to write simple unit tests
from unittest import TestCase
import zaiste
class TestZaiste(TestCase):
def test_is_string(self):
s = zaiste.cli()
self.assertTrue(isinstance(s, basestring))You can use Nose to easily run those tests
$ pip install nose
$ nosetestsNose integrates with setup.py
setup(
...
test_suite='nose.collector',
tests_require=['nose'],
)so you can just do
python setup.py testAdding Command Line Scripts
You can use scripts
setup(
...
scripts=['bin/zaiste-cli'],
...
)using the following script
#!/usr/bin/env python
import zaiste
print zaiste.cli()and put the script inside bin directory
zaiste/
zaiste/
__init__.py
setup.py
bin/
zaiste-cliin order to run it as
$ zaiste-cliAlternatively you can use console_scripts provided by setuptools so a Python
function can be directly registered as command-line script. It will generate a
standalone script shim which imports the module and calls the registered
function.
setup(
...
entry_points = {
'console_scripts': ['zaiste-cli=zaiste.cli:main'],
}
)with cli.py defined as:
import zaiste
def main():
print zaiste.cli()and put directly inside a module
zaiste/
zaiste/
__init__.py
cli.py
setup.pyThis method of adding command-line scripts is preferable as it is very easily testable:
from unittest import TestCase
from zaiste.cli import main
class TestConsole(TestCase):
def test_basic(self):
main()