Skip to main content

Read the latest stock news

Project description

py-packaging

This repo shows how to package, build python app and publication on pypi (The python packaging index).

In this tutorial, you’ll learn how to:

  • Prepare your Python package for publication
  • Handle versioning of your package
  • Build your package and upload it to PyPI
  • Understand and use different build systems

The python packaging standard is reviewed by Python Enhancement Proposals (PEPs), and implemented by the Python Packaging Authority (PyPA) working group.

The most important documents that define how Python packaging works are the following PEPs:

  • PEP 427 describes how wheels should be packaged.
  • PEP 440 describes how version numbers should be parsed.
  • PEP 508 describes how dependencies should be specified.
  • PEP 517 describes how a build backend should work.
  • PEP 518 describes how a build system should be specified.
  • PEP 621 describes how project metadata should be written.
  • PEP 660 describes how editable installs should be performed.

1. Prepare your Python package

There is no strict rule on how to organize the python package source. But we recommend you to use the below organization.

my_package/
│-- src/my_package/           # Package source code
│   │-- __init__.py       # Makes this a package
|   |-- __main__.py       # entry point of the package when run python -m my_package
│   │-- module1.py        # First module
│   │-- module2.py        # Second module
│   │-- subpackage1/       # A subpackage (optional)
│   │   │-- __init__.py
│   │   │-- submodule.py
│
│-- tests/                # Unit tests
│   │-- test_module1.py   # Tests for module1
│   │-- test_module2.py   # Tests for module2
│
│-- docs/                 # Documentation (optional)
│   │-- index.rst         # Main documentation file
│
│-- examples/             # Example scripts (optional)
│   │-- example_usage.py
│
|-- data/
|   |-- input.csv          # test input data
|   |-- output.parquet     # output example
|
│-- pyproject.toml        # Build system and dependency management (recommended)
│-- requirements.txt      # Dependencies list
│-- README.md             # Project overview and usage
│-- LICENSE               # License file
│-- .gitignore            # Git ignore file

The src/- structure is recommended, it provides several advantages as your project grows. You can read this page for more information. You can also read this article to learn different file layouts for different types of python application

1.1 src/my_package/

This folder contains all the source code. You can have simple modules (e.g. module1.py, etc.) or subpackages(subpackage1/, etc.)

The init.py defines what gets imported when import my_package is used. The main.py is the entry point of the package. It will be executed when user run python -m my_package.

1.2 tests/

Contains unit tests using unittest or pytest.

1.3 docs/

It contains the documentation of the package. The format can be Sphinx documentation generated by the docstring or Markdown files.

1.4 examples/

Helps users understand how to use the package.

1.5 data/

The sample input data, or required data to run the package correctly.

1.6 Build System & Dependencies

pyproject.toml: Preferred way to define dependencies and package metadata.

requirements.txt: Lists dependencies for easy installation.

1.7 Metadata & Automation

README.md: Project documentation. LICENSE: Defines the package’s license. .gitignore: Specifies files to exclude from version control.

2. A real world example

Now we will use a real world project to simulate how to build a python package.

2.1 Configuration

You can find the config.toml in src/stock_catcher. We store the file name which contains the French CAC 40 stock ticker.

[stock]
cac_40="CAC40_2024.csv"

TOML is a configuration file format that has gained popularity lately. Python uses it for the pyproject.toml file that you’ll learn about later. To dive deeper into TOML, check out this tutorial. tomllib library has been added to python standard library since python 3.11. So you should be able to read toml easily in python.

TOML files contain key-value pairs separated into sections, or tables. Our config file contains only one section, stock, with one key, cac_40.

2.2 init.py

The __init__.py file represents the root of your package. It is executed when the package is imported for the first time in a Python session.

It should usually be kept quite simple, but it’s a good place to put package constants, documentation, and so on.

In our example, we use importlib.resources to get the path of config.toml based on the package. This is especially helpful when you publish your package to PyPI and don’t have full control over where your package is installed and how it’s used. Resource files might even end up inside zip archives.

# Standard library imports
from importlib import resources

print("Executing __init__.py")

# Using try except ensures that you use tomllib if it’s available and that you fall back to tomli if it’s not.
try:
    import tomllib
except ModuleNotFoundError:
    # Third party imports
    import tomli as tomllib


# Version of the package
# Specifying __version__ is `strictly speaking` not necessary
# The importlib.metadata machinery uses project metadata to find version numbers. 
__version__ = "0.0.1"
# However, it’s still a useful convention to follow, and tools like Setuptools and Flit can use it to automatically


# Read the CAC40 stock ticker file path from the config file of package stock-catcher
_cfg = tomllib.loads(resources.read_text("stock_catcher", "config.toml"))

CAC40 = _cfg["stock"]["cac_40"]

2.3 main.py

The __main__.py is a special file inside a Python package that makes the package executable using python -m package_name.

Unlike __init__.py, it will not be executed during import. It will be only executed when python -m my_package (run package as a script) is called

2.4 catcher.py

This module contains some functions which can get stock information and filter them based on certain user defined condition.

The below import is interesting. Because it will not work b default, because stock_catcher package is not recognized in the current python env.

from stock_catcher import CAC40

To install the stock_catcher package in current python virtual env. you can use the below command

# install the package in editable mode, any change will be updated into the python virtual env
pip install -e /path/to/package

# in our case
pip install -e /home/pliu/git/py-packaging/src/stock_catcher

# or you can go the folder, and call the command on current folder
cd /home/pliu/git/py-packaging
 python -m pip install -e .

To do the pip install, it requires you to have a valid pyproject.toml.

3. How to use a package

The most common way to call a python module in a package is call the python file of the module. Below is an example

# if the module contains a main method, the main method will be called
python cacher.py

You can also use the -m option, it runs a script by specifying its module name instead of the filename:

# if the module contains a main method, the main method will be called
python -m cacher

4. Prepare the package for publication

4.1 Choose a catchy package name

All packages on PyPI need to have unique names. There are now several hundred thousand packages on PyPI, so chances are that your favorite name is already taken.

We will try to use the name stock_catcher, if it's already be taken, then we will add some prefix. For example we can go pf_stock_catcher.

The package name will be used to install the package(pip install stock_catcher).

The PyPI package name does not need to match the package name. For example, you can named the package as stock_catcher in PyPI, after installation, the package can be called catcher for import(import catcher).

The best practice is to keep them the same to avoid naming conflict. Because in one python environment, you cannot have two packages which have the same name.

4.2 Configure a build system for your package

A build system is responsible for creating the actual files that you’ll upload to PyPI, typically in the wheel or the source distribution (sdist) format. For a long time, this was done by distutils or setuptools. However, PEP 517 and PEP 518 introduced a way to specify custom build systems (e.g. Poetry, flit).

In this tutorial, we only show how to use setuptools as our build system. The main difference of these build systems is how you configure your package and build command to build and upload the package.

4.2.1 The pyproject.toml

The pyproject.toml file specify the build system of the package. You can specify setuptools by adding the following lines to pyproject.toml:

[build-system]
requires      = ["setuptools>=61.0.0", "wheel"]
build-backend = "setuptools.build_meta"

The minimal project information that you must include in your pyproject.toml is the following:

  • name: specifies the name of your package as it will appear on PyPI.
  • version: sets the current version of your package.

All other attributes are optional, but we recommend you to provide as much information as possible.

  • classifiers: describes your project using a list of classifiers. You should use these as they make your project more searchable.
  • dependencies: lists any dependencies your package has to third-party libraries. stock_cacher depends on pandas yfinance, and tomli.
  • project.urls: adds links that you can use to present additional information about your package to your users. You can include several links here.
  • project.scripts: creates command-line scripts that call functions within your package. In our case, the stock_catcher command will call the main() within the stock_catcher.__main__ module.

There are three ways to config the entry point of a package:

  • project.scripts
  • project.gui-scripts: specify GUI applications entry point
  • project.entry-points: specify plugins entry point

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

stock_catcher-0.0.1.tar.gz (22.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

stock_catcher-0.0.1-py3-none-any.whl (17.3 kB view details)

Uploaded Python 3

File details

Details for the file stock_catcher-0.0.1.tar.gz.

File metadata

  • Download URL: stock_catcher-0.0.1.tar.gz
  • Upload date:
  • Size: 22.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.11.10

File hashes

Hashes for stock_catcher-0.0.1.tar.gz
Algorithm Hash digest
SHA256 1f85082eb46b01e8d53ee3f315c95918edb29db3f0d02c81f8b4f110cbd067a7
MD5 7427d1bff3ce61813c5be5504feca306
BLAKE2b-256 5ed52bcd09a76d5cbfb552b36834b118c31cddf487e1fb7443e1b06fda265a49

See more details on using hashes here.

File details

Details for the file stock_catcher-0.0.1-py3-none-any.whl.

File metadata

  • Download URL: stock_catcher-0.0.1-py3-none-any.whl
  • Upload date:
  • Size: 17.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.11.10

File hashes

Hashes for stock_catcher-0.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 412ae51bde41867bc3b86e7824f57b8b945f5d94f71b3a795cc00563fb323146
MD5 c7e78c3039161cd9a58bba913e31265a
BLAKE2b-256 2778623dceffb32fb4fb6bdc1fcffafe0dc8eeccbc39ba1a96a496a7a84b2bf3

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page