Create a Python Package

PythonPythonBeginner
Practice Now

This tutorial is from open-source community. Access the source code

Introduction

In this lab, you will learn how to create and organize a Python package. Python packages are a great way to structure your code, making it more modular, reusable, and maintainable.

The objectives of this lab are to understand what a Python package is, create a basic package structure, organize related Python modules into a cohesive package, and update import statements to work with the new package structure.

This is a Guided Lab, which provides step-by-step instructions to help you learn and practice. Follow the instructions carefully to complete each step and gain hands-on experience. Historical data shows that this is a intermediate level lab with a 67% completion rate. It has received a 100% positive review rate from learners.

Understanding Python Packages

Before we start creating a Python package, let's understand what a Python package is. A Python package is essentially a directory. Inside this directory, there are multiple Python module files, which are just .py files containing Python code. Additionally, there is a special file named __init__.py. This file can be empty, but its presence indicates that the directory is a Python package. The purpose of this structure is to help you organize related code into a single directory hierarchy.

Packages offer several benefits. First, they allow you to structure your code logically. Instead of having all your Python files scattered around, you can group related functionality together in a package. Second, they help avoid naming conflicts between modules. Since packages create a namespace, you can have modules with the same name in different packages without any issues. Third, they make importing and using your code more convenient. You can import an entire package or specific modules from it with ease.

Now, let's take a look at the files we currently have in our project directory. To list the files, we'll use the following command in the terminal:

ls -l

When you run this command, you should see the following files:

portfolio.csv
reader.py
stock.py
structure.py
tableformat.py
validate.py

These Python files are all related and work together, but currently, they are just separate modules. In this lab, our goal is to organize them into a cohesive package called structly.

Let's briefly understand what each file does:

  • structure.py: This file defines a base Structure class and various descriptors. These descriptors are used for type validation, which means they help ensure that the data used in your program has the correct type.
  • validate.py: It contains validation functionality that is used by the structure module. This helps in validating the data according to certain rules.
  • reader.py: This file provides functions that are used to read CSV data. CSV (Comma-Separated Values) is a common file format for storing tabular data.
  • tableformat.py: It contains classes and functions that are used to format data into tables. This is useful when you want to display data in a more organized way.
  • stock.py: This file uses the other modules to define a Stock class and process stock data. It combines the functionality of the other modules to perform specific tasks related to stock data.

In the next step, we'll create our package structure.

✨ Check Solution and Practice

Creating the Package Structure

Now, we're going to create our Python package. But first, let's understand what a Python package is. A Python package is a way to organize related Python modules into a single directory hierarchy. It helps in managing and reusing code more effectively. To create a Python package, we need to follow these steps:

  1. Create a directory with the package name. This directory will serve as the container for all the modules that belong to the package.
  2. Create an __init__.py file inside this directory. This file is crucial because it makes Python recognize the directory as a package. When you import the package, the code in __init__.py is executed, which can be used to initialize the package.
  3. Move our Python module files into this directory. This step ensures that all the related code is grouped together within the package.

Let's create the package structure step by step:

  1. First, create a directory called structly. This will be the root directory of our package.
mkdir structly
  1. Next, create an empty __init__.py file inside the structly directory.
touch structly/__init__.py

The __init__.py file can be empty, but it's required to make Python treat the directory as a package. When you import the package, the code in __init__.py is executed, which can be used to initialize the package.

  1. Now, let's move our Python module files into the structly directory. These module files contain the functions and classes that we want to include in our package.
mv structure.py validate.py reader.py tableformat.py structly/
  1. Verify that all files have been moved correctly. We can use the ls -l command to list the contents of the structly directory.
ls -l structly/

You should see the following files listed:

__init__.py
reader.py
structure.py
tableformat.py
validate.py

Now we have created a basic package structure. The directory hierarchy should look like this:

project/
├── portfolio.csv
├── stock.py
└── structly/
    ├── __init__.py
    ├── reader.py
    ├── structure.py
    ├── tableformat.py
    └── validate.py

In the next step, we'll fix the import statements to make the package work correctly.

✨ Check Solution and Practice

Fixing Import Statements

Now, let's understand why we need to do this. When we moved our files into the structly package, the way Python looks for modules has changed. Import statements in each file need to be updated to match the new package structure. This is crucial because Python uses these import statements to find and use the code from other modules.

The structure.py file is very important to update. It imports functions and classes from the validate.py file. Since both of these files are now in the same structly package, we have to adjust the import statement accordingly.

Let's start by opening the structly/structure.py file in the editor. You can either click on structly/structure.py in the file explorer or run the following command in the terminal:

## Click on structly/structure.py in the file explorer or run:
code structly/structure.py

Once the file is open, look at the first line of the import statement. It currently looks like this:

from validate import validate_type

This statement was correct when the files were in a different structure. But now, we need to change it to tell Python to look for the validate module within the same package. So, we change it to:

from .validate import validate_type

The dot (.) before validate is a key part here. It's a special syntax in Python called a relative import. It tells Python to search for the validate module in the same package as the current module (which is structure.py in this case).

After making this change, make sure to save the file. Saving is important because it makes the changes permanent, and Python will use the updated import statement when you run your code.

Now, let's check our other files to see if they need any updates.

  1. structly/reader.py - This file doesn't import from any of our custom modules. That means we don't need to make any changes to it.
  2. structly/tableformat.py - Similar to the reader.py file, this one also doesn't import from any of our custom modules. So, no changes are required here either.
  3. structly/validate.py - Just like the previous two files, it doesn't import from any of our custom modules. Hence, we don't need to modify it.

In real - world programming, your projects might have more complex relationships between modules. When you move files around to create or modify a package structure, always remember to update the import statements. This ensures that your code can find and use the necessary modules correctly.

✨ Check Solution and Practice

Updating and Testing the stock.py Program

Now that we've created our package and fixed the internal imports, it's time to update the stock.py file to use our new package structure. A package in Python is a way to organize related modules together. It helps in keeping your codebase organized and makes it easier to manage and reuse code.

Open the stock.py file in the editor:

## Click on stock.py in the file explorer or run:
code stock.py

The current imports in stock.py are based on the old structure where all files were in the same directory. In Python, when you import a module, Python looks for the module in specific locations. In the old structure, since all files were in the same directory, Python could easily find the modules. But now, with the new package structure, we need to update the imports to tell Python where to find the modules within the structly package.

Update the stock.py file to look exactly like this:

## stock.py

from structly.structure import Structure, String, PositiveInteger, PositiveFloat

class Stock(Structure):
    name = String()
    shares = PositiveInteger()
    price = PositiveFloat()

    @property
    def cost(self):
        return self.shares * self.price

    def sell(self, nshares: PositiveInteger):
        self.shares -= nshares

if __name__ == '__main__':
    from structly.reader import read_csv_as_instances
    from structly.tableformat import create_formatter, print_table
    portfolio = read_csv_as_instances('portfolio.csv', Stock)
    formatter = create_formatter('text')
    print_table(portfolio, ['name','shares','price'], formatter)

The key changes are:

  1. Changed from structure import Structure, String, PositiveInteger, PositiveFloat to from structly.structure import Structure, String, PositiveInteger, PositiveFloat. This change tells Python to look for the structure module inside the structly package.
  2. Changed from reader import read_csv_as_instances to from structly.reader import read_csv_as_instances. Similarly, this change directs Python to find the reader module within the structly package.
  3. Changed from tableformat import create_formatter, print_table to from structly.tableformat import create_formatter, print_table. This ensures that Python locates the tableformat module in the structly package.

Save the file after making these changes. Saving the file is important because it makes sure that the changes you've made are stored and can be used when you run the program.

Now, let's test our updated code to ensure everything works correctly:

python stock.py

You should see the following output:

      name      shares       price
---------- ---------- ----------
      MSFT        100      51.23
       IBM         50       91.1
      AAPL         75     145.89
      ACME        125     123.45
       HPE         75       32.2

If you see this output, congratulations! You have successfully created a Python package and updated your code to use it. This means that your code is now organized in a more modular way, making it easier to maintain and expand in the future.

✨ Check Solution and Practice

Summary

In this lab, you have learned how to create and structure a Python package. Specifically, you understood the concept and usefulness of Python packages for code organization, created a basic package structure, moved Python modules into it, updated import statements, and modified code to use the package correctly.

These skills are crucial for developing larger Python applications, as proper code organization becomes increasingly important. Python packages help keep related code together, avoid naming conflicts, and make your code more reusable, maintainable, and shareable. Well - structured packages are a cornerstone of professional Python development as you continue your Python journey.