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 s
rc/-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_cacherdepends 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
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1f85082eb46b01e8d53ee3f315c95918edb29db3f0d02c81f8b4f110cbd067a7
|
|
| MD5 |
7427d1bff3ce61813c5be5504feca306
|
|
| BLAKE2b-256 |
5ed52bcd09a76d5cbfb552b36834b118c31cddf487e1fb7443e1b06fda265a49
|
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
412ae51bde41867bc3b86e7824f57b8b945f5d94f71b3a795cc00563fb323146
|
|
| MD5 |
c7e78c3039161cd9a58bba913e31265a
|
|
| BLAKE2b-256 |
2778623dceffb32fb4fb6bdc1fcffafe0dc8eeccbc39ba1a96a496a7a84b2bf3
|