mirror of
https://github.com/kennethreitz/python-guide.git
synced 2026-06-05 14:50:19 +00:00
197 lines
7.2 KiB
ReStructuredText
197 lines
7.2 KiB
ReStructuredText
.. _packaging-your-code-ref:
|
|
|
|
|
|
###################
|
|
Packaging Your Code
|
|
###################
|
|
|
|
.. image:: /_static/photos/36137234682_be6898bf57_k_d.jpg
|
|
|
|
Package your code to share it with other developers. For example,
|
|
to share a library for other developers to use in their application,
|
|
or for development tools like 'py.test'.
|
|
|
|
An advantage of this method of distribution is its well established ecosystem
|
|
of tools such as PyPI and pip, which make it easy for other developers to
|
|
download and install your package either for casual experiments, or as part of
|
|
large, professional systems.
|
|
|
|
It is a well-established convention for Python code to be shared this way.
|
|
If your code isn't packaged on PyPI, then it will be harder
|
|
for other developers to find it and to use it as part of their existing
|
|
process. They will regard such projects with substantial suspicion of being
|
|
either badly managed or abandoned.
|
|
|
|
The downside of distributing code like this is that it relies on the
|
|
recipient understanding how to install the required version of Python,
|
|
and being able and willing to use tools such as pip to install your code's
|
|
other dependencies. This is fine when distributing to other developers, but
|
|
makes this method unsuitable for distributing applications to end-users.
|
|
|
|
The `Python Packaging Guide <https://python-packaging-user-guide.readthedocs.io/>`_
|
|
provides an extensive guide on creating and maintaining Python packages.
|
|
|
|
|
|
*************************
|
|
Alternatives to Packaging
|
|
*************************
|
|
|
|
To distribute applications to end-users, you should
|
|
:ref:`freeze your application <freezing-your-code-ref>`.
|
|
|
|
On Linux, you may also want to consider
|
|
:ref:`creating a Linux distro package <packaging-for-linux-distributions-ref>`
|
|
(e.g. a .deb file for Debian or Ubuntu.)
|
|
|
|
|
|
*********************
|
|
For Python Developers
|
|
*********************
|
|
|
|
If you're writing an open source Python module, `PyPI <http://pypi.org>`_
|
|
, more properly known as *The Cheeseshop*, is the place to host it.
|
|
|
|
|
|
|
|
Pip vs. easy_install
|
|
--------------------
|
|
|
|
Use `pip <http://pypi.org/project/pip>`_. More details
|
|
`here <https://stackoverflow.com/questions/3220404/why-use-pip-over-easy-install>`_.
|
|
|
|
|
|
Personal PyPI
|
|
-------------
|
|
|
|
If you want to install packages from a source other than PyPI (say, if
|
|
your packages are *proprietary*), you can do it by hosting a simple HTTP
|
|
server, running from the directory which holds those packages which need to be
|
|
installed.
|
|
|
|
**Showing an example is always beneficial**
|
|
|
|
For example, if you want to install a package called :file:`MyPackage.tar.gz`,
|
|
and assuming this is your directory structure:
|
|
|
|
|
|
- archive
|
|
- MyPackage
|
|
- MyPackage.tar.gz
|
|
|
|
Go to your command prompt and type:
|
|
|
|
.. code-block:: console
|
|
|
|
$ cd archive
|
|
$ python -m http.server 9000
|
|
|
|
This runs a simple HTTP server running on port 9000 and will list all packages
|
|
(like **MyPackage**). Now you can install **MyPackage** using any Python
|
|
package installer. Using pip, you would do it like:
|
|
|
|
.. code-block:: console
|
|
|
|
$ pip install --extra-index-url=http://127.0.0.1:9000/ MyPackage
|
|
|
|
Having a folder with the same name as the package name is **crucial** here.
|
|
I got fooled by that, one time. But if you feel that creating a folder called
|
|
:file:`MyPackage` and keeping :file:`MyPackage.tar.gz` inside that is
|
|
*redundant*, you can still install MyPackage using:
|
|
|
|
.. code-block:: console
|
|
|
|
$ pip install http://127.0.0.1:9000/MyPackage.tar.gz
|
|
|
|
pypiserver
|
|
++++++++++
|
|
|
|
`pypiserver <https://pypi.org/project/pypiserver>`_ is a minimal PyPI
|
|
compatible server. It can be used to serve a set of packages to easy_install
|
|
or pip. It includes helpful features like an administrative command
|
|
(``-U``) which will update all its packages to their latest versions
|
|
found on PyPI.
|
|
|
|
|
|
S3-Hosted PyPi
|
|
++++++++++++++
|
|
|
|
One simple option for a personal PyPI server is to use Amazon S3. A
|
|
prerequisite for this is that you have an Amazon AWS account with an S3 bucket.
|
|
|
|
1. **Install all your requirements from PyPi or another source**
|
|
2. **Install pip2pi**
|
|
|
|
* :code:`pip install git+https://github.com/wolever/pip2pi.git`
|
|
|
|
3. **Follow pip2pi README for pip2tgz and dir2pi commands**
|
|
|
|
* :code:`pip2tgz packages/ YourPackage` (or :code:`pip2tgz packages/ -r requirements.txt`)
|
|
* :code:`dir2pi packages/`
|
|
|
|
4. **Upload the new files**
|
|
|
|
* Use a client like Cyberduck to sync the entire :file:`packages` folder to your s3 bucket.
|
|
* Make sure you upload :code:`packages/simple/index.html` as well as all new files and directories.
|
|
|
|
5. **Fix new file permissions**
|
|
|
|
* By default, when you upload new files to the S3 bucket, they will have the wrong permissions set.
|
|
* Use the Amazon web console to set the READ permission of the files to EVERYONE.
|
|
* If you get HTTP 403 when trying to install a package, make sure you've set the permissions correctly.
|
|
|
|
6. **All done**
|
|
|
|
* You can now install your package with :code:`pip install --index-url=http://your-s3-bucket/packages/simple/ YourPackage`.
|
|
|
|
.. _packaging-for-linux-distributions-ref:
|
|
|
|
|
|
***********************
|
|
For Linux Distributions
|
|
***********************
|
|
|
|
Creating a Linux distro package is arguably the "right way" to distribute code
|
|
on Linux.
|
|
|
|
Because a distribution package doesn't include the Python interpreter, it
|
|
makes the download and install about 2-12 MB smaller than
|
|
:ref:`freezing your application <freezing-your-code-ref>`.
|
|
|
|
Also, if a distribution releases a new security update for Python, then your
|
|
application will automatically start using that new version of Python.
|
|
|
|
The bdist_rpm command makes `producing an RPM file <https://docs.python.org/3/distutils/builtdist.html#creating-rpm-packages>`_
|
|
for use by distributions like Red Hat or SuSE trivially easy.
|
|
|
|
However, creating and maintaining the different configurations required for
|
|
each distribution's format (e.g. .deb for Debian/Ubuntu, .rpm for Red
|
|
Hat/Fedora, etc.) is a fair amount of work. If your code is an application that
|
|
you plan to distribute on other platforms, then you'll also have to create and
|
|
maintain the separate config required to freeze your application for Windows
|
|
and OS X. It would be much less work to simply create and maintain a single
|
|
config for one of the cross platform :ref:`freezing tools
|
|
<freezing-your-code-ref>`, which will produce stand-alone executables for all
|
|
distributions of Linux, as well as Windows and OS X.
|
|
|
|
Creating a distribution package is also problematic if your code is for a
|
|
version of Python that isn't currently supported by a distribution.
|
|
Having to tell *some versions* of Ubuntu end-users that they need to add `the
|
|
'dead-snakes' PPA <https://launchpad.net/~fkrull/+archive/ubuntu/deadsnakes>`_
|
|
using `sudo apt-repository` commands before they can install your .deb file
|
|
makes for an extremely hostile user experience. Not only that, but you'd have
|
|
to maintain a custom equivalent of these instructions for every distribution,
|
|
and worse, have your users read, understand, and act on them.
|
|
|
|
Having said all that, here's how to do it:
|
|
|
|
* `Fedora <https://fedoraproject.org/wiki/Packaging:Python>`_
|
|
* `Debian and Ubuntu <http://www.debian.org/doc/packaging-manuals/python-policy/>`_
|
|
* `Arch <https://wiki.archlinux.org/index.php/Python_Package_Guidelines>`_
|
|
|
|
Useful Tools
|
|
------------
|
|
|
|
- `fpm <https://github.com/jordansissel/fpm>`_
|
|
- `alien <http://joeyh.name/code/alien/>`_
|
|
- `dh-virtualenv <https://dh-virtualenv.readthedocs.io/>`_ (for APT/DEB omnibus packaging)
|