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.
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 baseStructureclass 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 thestructuremodule. 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 aStockclass 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.
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:
- Create a directory with the package name. This directory will serve as the container for all the modules that belong to the package.
- Create an
__init__.pyfile 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__.pyis executed, which can be used to initialize the package. - 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:
- First, create a directory called
structly. This will be the root directory of our package.
mkdir structly
- Next, create an empty
__init__.pyfile inside thestructlydirectory.
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.
- Now, let's move our Python module files into the
structlydirectory. 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/
- Verify that all files have been moved correctly. We can use the
ls -lcommand to list the contents of thestructlydirectory.
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.
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.
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.structly/tableformat.py- Similar to thereader.pyfile, this one also doesn't import from any of our custom modules. So, no changes are required here either.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.
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:
- Changed
from structure import Structure, String, PositiveInteger, PositiveFloattofrom structly.structure import Structure, String, PositiveInteger, PositiveFloat. This change tells Python to look for thestructuremodule inside thestructlypackage. - Changed
from reader import read_csv_as_instancestofrom structly.reader import read_csv_as_instances. Similarly, this change directs Python to find thereadermodule within thestructlypackage. - Changed
from tableformat import create_formatter, print_tabletofrom structly.tableformat import create_formatter, print_table. This ensures that Python locates thetableformatmodule in thestructlypackage.
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.
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.