A minimal python packaging example
Packaging your python code as a python package lets you pip install it and use it from any place in your computer
Overview
Python is one of the best programming languages ever. However, when your python project gets bigger with multiple packages and files, some things can get tricky. One is importing from different packages from different locations.
I’ve had this problem and could not find a good solution without doing appending unimportable
packages’ paths to the scripts needed (with sys.path.append('<dir>')
) which is ugly and not a good practice.
As a solution, you can have your core package pip installed alongside your python libraries so that they can be imported from anywhere. Here’s how…
Package description
Here’s my directory structure. I have my core modules in my_pkg and a sub module sub_pkg inside
pkging_ex/
├── my_pkg
│ ├── foolib.py
│ ├── __init__.py
│ └── sub_pkg
│ ├── barlib.py
│ └── __init__.py
└── setup.py
Here’s the content of mypkg
#mypkg/foolib.py
__all__ = ['foo', 'CFoo']
def foo():
print('Foo function')
class CFoo:
def __init__(self):
print('CFoo class')
#mypkg/__init__.py
from .foolib import *
The __init__.py
has that import because I want to import the function foo()
as mypkg.foo
not mypkg.foolib.foo
which would be the case if I didn’t have that import statement.
Here’s the content of mypkg/sub_pkg
#mypkg/sub_pkg/barlib.py
__all__ = ['bar']
from ..foolib import foo, CFoo
def bar():
print('Calling foo from bar')
foo()
#mypkg/sub_pkg/__init__.py
from .barlib import *
The __all__
list at the top of modules makes sure that only the attributes specified in that list gets imported if
you do an import *
from the module.
Installing
Now we need a setup.py specifying how to handle the packaging. Here’s mine for this package
import setuptools
setuptools.setup(
name="my_new_pkg", # Some name for the package
version="0.0.1",
author="Teshan Liyanage",
author_email="teshan@example.com",
description="A small example package",
packages=setuptools.find_packages(),
python_requires='>=3.6' # Say we need minimum python 3.6
)
Now just do pip install .
Here’s a simple sample test code to test if our package got installed correctly.
from my_pkg import foo, CFoo
from my_pkg.sub_pkg import bar
c = CFoo()
bar()
You can run this and see that all the functions and classes are working fine if the package got installed correctly.
Uninstalling
Just pip uninstall my_new_pkg
where ‘my_new_pkg’ is the name given to the package in the setup.py
Python packaging has many more capabilities and implications. Here I have only demonstrated a minimal example. Refer to this for a more detailed packaging guideline.