19

Please show the simple and up to date standard way to create a python package for python 2.x

I'd prefer to use pip for installing the package later.

The package should contain a single class:

class hello:
  def greet(self):
    print "hello"

One should be able to do the following later:

pip install my_package-0.1.1....

And then using it:

from my_package import hello

h = hello.hello()
h.greet()

What I am asking for is:

  • The directory and file layout
  • Contents of the files
  • command to create the distributable package file
  • command to install the package from the distributable package file (using preferably pip)

There are several howtos that I found but I am still not sure how this very simple and stripped down case (no nested packages, removal off all files and features that can be omitted for the most simple case) would be handled and which is the modern way to do it.

I would like this question to enter community wiki state, so you won't get any points and I will give enough time and will mark an answer accepted after several days, also considering the votes and comments.

Edit:

I have a first running example that I want to share, I used Marius Gedminas's answer for it. It does not contain everything that should be there, but it works, so it can demonstrate the core of the technical process. To add more necessary parts please read Marius's answer below.

Directory structure:

MyProject/
    setup.py
    my_package.py
    README.txt
    MANIFEST.in

setup.py:

from setuptools.import setup
setup(name='MyProject',
      version='0.1',
      py_modules=['my_package'])

my_package.py:

class hello:
  def greet(self):
    print "hello"

MANIFEST.in:

include *.txt

To create the package from this folder, go into the folder MyProject and run:

$ python setup.py sdist

This will create a file MyProject-0.1.tar.gz in a subfolder dist/. Copy this file to a folder on the target machine.

On the target machine run this command in the folder containing MyProject-0.1.tar.gz:

sudo pip install MyProject-0.1.tar.gz

It can be necessary to logout and re-login on the target machine now, so the package will be found. Afterwards you can test the package on the target machine using the python shell:

$ python
>>> import my_package
>>> h = my_package.hello()
>>> h.greet()
hello
>>> 

Once this works please remember to add the other necessary contents, see Marius's answer below.

mit
  • 11,083
  • 11
  • 50
  • 74
  • The point of this question is to pick a modern approach and then strip almost everything that can be stripped so it still works. – mit Nov 11 '10 at 15:40

2 Answers2

33

Start simple

Simplest one-file package:

MyProject/
    setup.py
    my_package.py

Simplest setup.py:

from setuptools import setup
setup(name='MyProject',
      version='0.1',
      author='Your Name',
      author_email='your.name@example.com',
      license='MIT',
      description='Example package that says hello',
      py_modules=['my_package'])

Including extra files in the package

Next you should probably add a README:

MyProject/
    MANIFEST.in
    README.rst
    setup.py
    my_package.py

Note the new file -- MANIFEST.in. It specifies which non-Python files ought to be included in your source distribution:

include *.rst

People will tell you "oh, skip the manifest, just add the files to source control, setuptools will find them". Ignore that advice, it's too error-prone.

Making the PyPI page useful

It's useful to make the README.rst available for people to view online, on the Python Package Index. So change your setup.py to do

from setuptools import setup
with open('README.rst') as f:
    readme = f.read()
setup(name='MyProject',
      ...
      description='Example package that says hello',
      long_description=readme,
      ...)

Use ReStructuredText markup for prettier pages. Use

python setup.py --long-description | rst2html

to catch ReStructuredText errors early.

More than one Python module in a package

One file will not be enough soon, so change it to a package (confusing terminology warning: Python package as in a directory with a __init__ py, not as in a distributable self-contained archive):

MyProject/
    MANIFEST.in
    README.rst
    setup.py
    my_package/
        __init__.py
        some_module.py

and change setup.py to

from setuptools import setup, find_packages
with open('README.rst') as f:
    readme = f.read()
setup(name='MyProject',
      version='0.2',
      author='Your Name',
      author_email='your@email',
      license='MIT',
      description='Example package that says hello',
      long_description=readme,
      packages=find_packages())

Releasing to the public

Get a PyPI account -- you only need to do this once.

To make a release, make sure the version number in setup.py is correct, then run

python setup.py sdist register upload

That's it.

Telling people to install it

Tell them to

pip install MyProject

(same name you specified in setup.py as the name argument to setup())

Marius Gedminas
  • 11,010
  • 4
  • 41
  • 39
  • 3
    I'm bending the question about "simplest" here. While I absolutely agree that it's important to start simple, eventually you need to grow. When that happens, the growth path should be clear. – Marius Gedminas Nov 11 '10 at 17:35
  • 4
    I think you have found a good balance between simple and also including the most essential extras. – mit Nov 11 '10 at 17:43
  • wouldn't the "simplest" be to include everything in the package namespace, e.g. `dir/__init__.py`? – Tim McNamara Nov 11 '10 at 19:05
  • You mean put __init__.py in the top level of the project directory? I don't know; I haven't ever tried that. It would make setup importable from your package; I don't know how I feel about that. I t might make testing your code without installing harder. I prefer to keep files inside my installable python package separate from support files that live outside that package. – Marius Gedminas Nov 13 '10 at 18:58
  • What is the `py_modules` parameter of `setuptools.setup`? It's not documented on http://pythonhosted.org//setuptools/setuptools.html#developer-s-guide and in the help content. – Kalle Richter Dec 29 '14 at 06:41
  • @KarlRichter: setuptools extends [distutils](https://docs.python.org/2/distutils/introduction.htm), so you have to check the documentation of both to get the full picture. It's rather annoying. Anyway, here's the [API reference that defines py_modules](https://docs.python.org/2/distutils/apiref.html?highlight=py_modules#module-distutils.core). – Marius Gedminas Dec 29 '14 at 20:48
4

The following is copied from the Distutils Tutorial.

File layout:

top
|-- package
|   |-- __init__.py
|   |-- module.py
|   `-- things
|       |-- cross.png
|       |-- fplogo.png
|       `-- tick.png
|-- runner
|-- MANIFEST.in
|-- README
`-- setup.py

To make the installation tarball, you simply run:

python setup.py sdist

To install the package, use pip or easy_install:

pip install my_package-1.2.3.tar.bz2

or

easy_install my_package-1.2.3.tar.bz2

Also, you can upload it to PyPI, first register it:

python setup.py register

then upload the source tarball

python setup.py sdist upload

You can upload binary eggs as well (though not necessary):

python setup.py bdist_egg upload

Then folks can install it like this:

pip install my_package==1.2.3

or,

easy_install my_package==1.2.3
Attila O.
  • 15,659
  • 11
  • 54
  • 84
  • @mit ah well; if you want to keep the bare minimum, `__import__('setuptools').setup(name='myapp')` is sufficient :) – Attila O. Nov 11 '10 at 15:53
  • Uploading bdist_eggs isn't just unnecessary but can be actively harmful. Only do that if you're building a package for Windows that needs a C compiler to install. – Marius Gedminas Nov 11 '10 at 17:04
  • @Marius Gedminas can you please cite your source on the harmfulness of eggs? I don't use them much, but they can be useful for folks without development libraries installed (if package has C extensions). As for windows, `bdist_wininst` might work better, as it also works like an egg (`easy_install` and `pip` can unpack them), but lets users install via the GUI interface too. – Attila O. Nov 11 '10 at 22:49
  • 1
    I don't have any URLs handy, sorry. It's a result of many mailing list conversations, mostly, about problems people had experienced with incompatible binary .egg packages on Linux platforms. Linux doesn't have a well-defined Python ABI -- .so files built for one version of one distribution will most likely fail to work on a different distro, or even on a different version of the same distro. As a result, my rule of thumb is: only build bdist_egg on Windows. – Marius Gedminas Nov 13 '10 at 18:53