How to Create Local Python Packages: A Step-by-Step Guide

If you’ve ever found yourself copying the same utility functions or helper scripts between multiple Python projects, then maybe it’s time to consider building a local Python package. Local packages allow you to group related code into reusable modules that can be easily maintained, tested, and shared across projects.

Whether you’re working on small scripts or scaling up to production-grade applications, structuring your code as a local package keeps things clean, organized, and future-proof.

Why Local Packages Matter

Creating a local package is more than just a tidy way to group code—it’s a best practice that improves your overall development workflow.

Here’s why developers (myself included) love using them:

  • Reusability: Avoid rewriting or copying code between projects.
  • Maintainability: Isolate changes and debug modules without breaking the entire app.
  • Team collaboration: Everyone on the team can follow the same structure and reuse common tools.
  • Easier testing: Run unit tests on specific modules without touching the rest of the project.
  • Ready for distribution: With a few tweaks, a local package can be uploaded to PyPI for public use.

Step 1: Set Up Your Development Environment

Before jumping into writing code, make sure your environment is ready:

  1. Install Python: Use the latest version if possible.
  2. Pick an Editor: VS Code or PyCharm are popular choices.

Create a Virtual Environment: Keep dependencies isolated.

  1. Install Packaging Tools:
  1. Keeping your environment clean helps avoid conflicts later when testing or distributing your package.

Step 2: Create the Package Directory Structure

The directory structure is the backbone of any good Python package.

Here’s a typical layout:

Step 3: Write Your Modules and Scripts

Now that the skeleton is ready, start writing your logic. Break functionality into separate .py files:

  • Use descriptive names like utils.py, math_ops.py, or api_handler.py.
  • Group-related functionality is logical.

If you need an entry point (e.g., a CLI), add a script with:

python
CopyEdit
if __name__ == “__main__”:

    # Your code here

Keep functions clean, use docstrings, and follow PEP 8 guidelines for readability.

Step 4: Add the __init__.py File

This file is small but mighty.

python

CopyEdit

# my_package/__init__.py

from .module1 import my_function

from .module2 import my_class

By doing this, anyone using your package can import with:

python

CopyEdit

from my_package import my_function

You can also keep it empty if you don’t want to expose anything directly.

Step 5: Test Your Package Locally

Before distributing your package, test it locally to make sure it behaves as expected.

  1. Navigate to the root folder (where setup.py lives).

Install the package locally:

bash
CopyEdit
pip install .

Try importing it in another Python file or the Python shell:

python
CopyEdit
from my_package import my_function

  1. Write unit tests in the /tests folder to cover critical paths.

Step 6: Add Setup Metadata

Create a setup.py file to define metadata and dependencies:

python

CopyEdit

from setuptools import setup, find_packages

setup(

    name=”my_package”,

    version=”0.1.0″,

    description=”A simple local Python package”,

    author=”Your Name”,

    packages=find_packages(),

    install_requires=[“requests”],  # add actual dependencies

)

Optionally, add:

  • long_description from README.md
  • classifiers for Python version support

Step 7: Manage Dependencies

To ensure others can use your package easily, list your dependencies in a requirements.txt:

shell

CopyEdit

requests>=2.20.0

pandas>=1.1.0

This way, users can install them with:

bash

CopyEdit

pip install -r requirements.txt

Also include any dev tools you use for testing or linting (like pytest, flake8, etc.).

Step 8: Install and Use in Other Projects

To use your local package in another project:

  1. Navigate to the project folder.
  2. Use pip’s editable mode:

bash

CopyEdit

pip install -e /path/to/my_package

Any changes you make to the package will reflect immediately in the other project.

Step 9: Update Versions and Changelog

Every time you make a meaningful update:

  • Bump the version in setup.py or __init__.py (use semantic versioning: MAJOR.MINOR.PATCH)

Document the changes in a CHANGELOG.md file:

markdown
CopyEdit
## [0.2.0] – 2025-07-01

– Added support for async processing

– Fixed bug in error handler

This makes your project professional and easier to maintain.

Step 10: Common Troubleshooting Tips

Here are frequent issues you might run into:

IssueSolution
ImportError: No module namedCheck __init__.py is present and your path is correct
pip install . failsValidate setup.py has all required fields
Dependencies missingMake sure install_requires is properly filled
Wrong version installedUse pip uninstall first, then reinstall
PYTHONPATH errorsUse a virtual environment to avoid system-level conflicts

Best Practices

Here are some extra tips to level up your packaging game:

  • ✅ Follow PEP 8 naming conventions
  • ✅ Keep your package modular
  • ✅ Write unit tests early
  • ✅ Add README.md with installation and usage instructions
  • ✅ Use Git or another VCS to track your changes
  • ✅ Document your modules and functions well

Conclusion and Next Steps

Now that you understand how to build local Python packages, here’s how to grow from here:

  1. Create your own package: Start with a utility module you use often.
  2. Practice using setup.py and virtual environments.
  3. Write tests to validate your code’s reliability.
  4. Try publishing on PyPI: Look into twine to upload your first public package.
  5. Explore pyproject.toml and the newer setuptools.build_meta for modern packaging.

Creating local Python packages is a simple yet impactful skill. It improves how you work, how your team collaborates, and how you scale your codebase. Start small, experiment, and you’ll soon wonder how you lived without it.

Previous Article

Getting Started with Protocol Buffers (Protobuf): A Faster Alternative to JSON and XML

Next Article

Choosing the Right Programming Language: A Guide to Use Cases and Strengths

Subscribe to our Newsletter

Subscribe to our email newsletter to get the latest posts delivered right to your email.
Pure inspiration, zero spam ✨