Adventures in Machine Learning

Demystifying Python Packaging: From Evolution to Publication

Get to Know Python Packaging

Python has been around since the early 90s, and it has come a long way since then. One of the most significant improvements is the way Python is packaged.

Python packaging allows you to download, install, and manage third-party libraries or packages easily. In this article, we will take you on a journey of Python packaging, from its evolution to PyPA (Python Packaging Authority) and introduce you to the PyPI.

Evolution of Python Packaging

Historically, packaging in Python was messy and error-prone; developers used various methods to package and distribute their code. In 2001, the “distutils” standard library was introduced, making packaging more manageable.

Later in 2008, “setuptools” was introduced, which is the most widely used packaging tool today.

In the beginning, “setuptools” faced many issues with package management.

This led to the formation of PyPA, a community-driven, open-source project that aims to standardize, modernize, and simplify Python packaging. Today, PyPA encompasses many packaging tools, including “setuptools,” “pip,” “wheel,” and “twine.” PyPA works to ensure compatibility and interoperability between these tools.

PyPI

PyPI stands for Python Packaging Index, and it is the repository that stores all the Python packages created by developers worldwide.

PyPI is a vast, reliable source of Python packages that can be installed via the “pip” command.

PyPI has over 300,000 packages, and the number continues to grow each day.

The repository also facilitates uploading your own packages with the “twine” command. This way, developers can upload their packages to PyPI for others to use.

Now that we have covered the basics of Python packaging, let us dive deep and explore how to create a small Python package.

Create a Small Python Package

Reader package

The first step in creating a Python package is to come up with an idea or a concept. For this tutorial, we will create a simple “reader” package that reads a file and returns its contents.

We will use this package to demonstrate how to create a Python package from scratch.

Understanding the Directory Structure

Next, let us cover the directory structure required for our Reader package. The following is a suggested directory structure:

reader/
  |__init__.py
  |__main__.py
  |reader.py
  |tests/
      |__init__.py
      |test_reader.py
  

Here, the “__init__.py” file is needed for Python to treat the “reader” directory as a package.

The “main.py” file is optional and is used to execute our package as a script. The “reader.py” file is where our package’s functionality will be defined.

Finally, the “tests” directory contains all the tests for our package.

To make a Python package installable, we need to create our “setup.py” file:

from setuptools import setup, find_packages

setup(
    name="reader",
    version="0.1.0",
    packages=find_packages(where="src"),
    package_dir={"": "src"},
    entry_points={
        "console_scripts": [
            "reader = reader.cli:main"
        ]
    },
    install_requires=[
        "click"
    ]
)

Let us briefly go through what each parameter does. The “name” parameter is the name of our package, “version” is the package version, and “packages” specify the list of packages to include in the distribution.

We use the “find_packages” function to automatically discover the packages in our “src” directory. The “package_dir” parameter specifies that our source files are in the “src” directory.

The “entry_points” parameter is used to create entry points for our package, allowing it to run as a script. In this case, we create a command-line interface using the “click” library.

Finally, the “install_requires” parameter specifies the Python libraries that our package relies on.

Conclusion

In conclusion, Python packaging has come a long way, and thanks to PyPA, packaging and distributing Python packages have never been easier. In this article, we’ve explored the basics of Python packaging, introduced you to the PyPI, and shown you how to create a simple Python package from scratch.

We hope that you’ve found this article informative and that it has inspired you to create your own Python packages.

Use the Real Python Reader

So far, we have learned about Python packaging and how to create a small package in Python. In this section, we will demonstrate how to use the “Real Python Reader” package to read and print the contents of a file.

We will also go over how to run the Reader package command using its “__main__.py” file.

Examples of Reader Package Output

The Real Python website is a fantastic resource for Python tutorials. We will use the “Real Python Reader” package to read one of their tutorials and print its contents.

To do so, we will first install the package by running the following command:

pip install real-python-reader

Now that we have installed the package, let’s import it into our Python code and use it to read a tutorial. We will use the “requests” library to download the tutorial and pass it to the “read_url” function of the Reader package.

import requests
from real_python_reader.reader import read_url

# URL of the tutorial
url = "https://realpython.com/python-type-checking/"

# Download the HTML content of the tutorial
html_content = requests.get(url).content.decode("utf-8")

# Read the content of the tutorial using the Real Python Reader
output = read_url(html_content)

# Print the output
print(output)

When we run this code, we will see the content of the tutorial printed to the console as plain text. This is the power of the Real Python Reader package.

Running Reader Package Command

We can also run the Real Python Reader package as a command-line tool using the “__main__.py” file. To do so, we need to add an “entry_point” to our “setup.py” file:

from setuptools import setup, find_packages

setup(
    ...
    entry_points={
        "console_scripts": [
            "real-python-reader = real_python_reader.__main__:main"
        ]
    },
    ...
)

This tells Setuptools to create an executable script called “real-python-reader,” which runs the “main” function in the “__main__.py” module.

Once we have added the entry-point to our “setup.py” file, we can install the package and run the “real-python-reader” command from our terminal:

pip install real-python-reader
real-python-reader https://realpython.com/python-type-checking/

This will print the content of the tutorial to the console.

Prepare Your Package for Publication

Now that we have created our Python package, we may want to publish it to PyPI so that others can use and install it easily. To do so, we need to prepare our package correctly.

Naming Your Package

When it comes to naming our package, we need to think about two different names: the package name and the PyPI name. The package name is the name we will use in our Python code to import the package.

It is also the name that we will use in our “setup.py” file under the “name” parameter. The PyPI name is the name that other people will use to download and install our package through “pip.” It should be unique and meaningful.

For example, let’s say we want to create a package for interacting with the GitHub API. We could name our package “github-api” internally.

However, since that name is likely already taken on PyPI, we would need to choose a unique name such as “my-github-api” for the PyPI name.

Configuring Your Package

To configure our package correctly, we need to use a build system. A popular build system for Python packages is “setuptools.” When using “setuptools,” we need to create a “pyproject.toml” file with the following contents:

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

This tells “setuptools” to use the “setuptools.build_meta” backend to build and distribute our package.

We also need to include a “README.md” file, a “LICENSE” file, and a “setup.py” file in our project directory. The “setup.py” file should have the following contents:

from setuptools import setup, find_packages

setup(
    name="my-github-api",
    version="0.1.0",
    packages=find_packages(where="src"),
    package_dir={"": "src"},
    install_requires=[
        "requests"
    ]
)

The “name” parameter is the PyPI name we chose earlier, the packages are discovered using the “find_packages” function, and the package directory is set to the “src” directory using the package_dir parameter. We also have the “install_requires” parameter, which specifies the Python libraries that our package relies on.

Conclusion

In this article, we have explored how to use the Real Python Reader package to read HTML content and print its contents using Python code. We have also shown how to run the package as a command-line tool using the “__main__.py” file.

Finally, we have gone through the steps to prepare our package for publication, including naming our package and configuring it using “setuptools.” We hope that this article has given you a better understanding of Python packaging and how to create and publish your own Python packages.

Name Your Package

Choosing a name for your Python package can be challenging. Ideally, the name should be unique, memorable, and descriptive of the package’s functionality.

In this section, we will discuss the challenges that come with naming packages and how to choose a name that is suitable for your package.

Naming Challenges

One of the most significant challenges in naming a package is finding a name that is not already taken. PyPI has over 300,000 packages, which means that many of the popular and obvious names are already taken.

Choosing a name that is too common may lead to confusion and difficulty finding your package. Another challenge is choosing a name that is descriptive of your package’s functionality.

A good name should convey what the package does in a clear and concise way. This can be a tough challenge, especially if your package is complex or multifaceted.

Finally, it’s important to choose a name that is easy to remember and spell. A name that is too complicated or difficult to spell may cause users to avoid your package altogether.

To avoid these challenges, there are a few naming strategies you can use:

  • Use a creative or made-up word that is easy to remember. Examples include “numpy,” “pytest,” and “django.”
  • Combine two or more words to create a descriptive name. Examples include “blackjack-api,” “bookshelf,” and “pandas-datareader.”
  • Add a prefix or suffix to a descriptive name to create a unique name. Examples include “django-rest-framework,” “requests-mock,” and “typing-extensions.”

Once you have chosen a name, be sure to check that it is not already taken on PyPI or other package repositories.

Configure Your Package

Configuring your package is an essential step in creating a Python package. It involves defining the package’s metadata, dependencies, and build system configuration.

In this section, we will discuss the build system and how to configure it using “setuptools.”

Build System

A build system is a tool that automates the process of building, testing, and distributing software. In Python, “setuptools” is the most popular build system.

“setuptools” is a Python module that provides infrastructure for building, distributing, and installing Python packages. To use “setuptools,” you need to create a “setup.py” file in your project directory.

This file defines the metadata for your package, such as its name, version, and author. It also specifies which Python packages your package depends on and any extra requirements needed for development or testing.

from setuptools import setup, find_packages

setup(
    name="example-package",
    version="0.0.1",
    author="Your Name",
    description="A short description of your package.",
    packages=find_packages(),
    install_requires=[
        "numpy>=1.18",
        "requests>=2.22",
    ],
    extras_require={
        "dev": [
            "pytest>=6.0",
            "black>=20.8b1",
        ]
    },
)

In the “setup()” function, we define the metadata for our package. The “name” parameter is the name of our package, and the “version” parameter is the current version.

We also specify the author and a brief description of our package. We use the “find_packages()” function to discover and include all packages in our project directory.

We then define the package dependencies using the “install_requires” parameter. In this case, our package depends on “numpy” and “requests.”

We also use the “extras_require” parameter to specify extra requirements needed for development or testing.

In this case, we add “pytest” and “black” as dev dependencies.

Pyproject.toml

“Pyproject.toml” is a configuration file that specifies the build system for your Python package.

It is used by build systems such as “setuptools” and “poetry” to manage your package’s dependencies and build process. Here’s an example “pyproject.toml” file using “setuptools” as the build system:

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

This tells “setuptools” that our package requires version 40.8.0 or later and “wheel” as a dependency.

The “build-backend” parameter specifies the build backend for “setuptools.”

Conclusion

Naming and configuring your Python package are essential steps in creating a successful package. By choosing the right name and setting up your build system correctly, you increase the chances of your package being discovered and used by others.

We hope this article has provided valuable insights into the challenges of naming packages and configuring them using “setuptools” and “pyproject.toml.”

In this article, we’ve discussed the importance of naming and configuring Python packages. When naming your package, you must choose a unique, descriptive, and memorable name that is easy to spell.

We also explored the challenges that come with naming a package, such as finding a name that is not already taken and conveying the package’s functionality clearly. Configuring your package involves defining its metadata, dependencies, and build system configuration.

We discussed the “setuptools” build system and its configuration via the “pyproject.toml” file. Proper naming and configuring of your Python packages can increase their chances of being discovered and used by others.

By following the best practices outlined in this article, you can create successful packages that will be sought-after by the community.

Popular Posts