Introduction
In this lab, you will learn about Python modules, which are files containing Python code that can be imported and used in other programs. This modular approach promotes code reuse and helps organize programs into logical components.
You will understand what Python modules are and why they are useful, learn how to create your own modules, practice using the import statement in different ways, and grasp the concept of a main module and when code executes. Prerequisites include a basic understanding of Python syntax and functions, and familiarity with creating and running Python scripts. It's recommended to restart your Python interpreter session before starting this exercise for a clean environment.
Understanding Python Modules
In Python, a module is like a container that holds Python definitions and statements. It's essentially a file, and the name of this file is the module name with the .py extension added at the end. Think of modules as toolboxes. They help you organize your Python code in a logical way, making it easier to reuse and maintain. Just like you'd keep different tools in separate boxes for better organization, you can group related Python code into different modules.
Let's take a look at the files that have been set up for this lab:
- First, we'll open the
stock.pyfile in the editor to see what's inside. To do this, we'll use the following commands. Thecdcommand changes the directory to theprojectfolder where our file is located, and thecatcommand displays the contents of the file.
cd ~/project
cat stock.py
This stock.py file defines a Stock class. A class is like a blueprint for creating objects. In this case, the Stock class represents a stock. It has attributes (which are like characteristics) for the stock's name, the number of shares, and the price. It also has a method (which is like a function associated with the class) to calculate the cost of the stock.
- Next, let's examine the
pcost.pyfile. We'll use thecatcommand again to view its contents.
cat pcost.py
This file defines a function called portfolio_cost(). A function is a block of code that performs a specific task. The portfolio_cost() function reads a portfolio file and calculates the total cost of all the stocks in that portfolio.
- Now, let's look at the sample portfolio data. We'll use the
catcommand to view the contents of theportfolio.datfile.
cat portfolio.dat
This file contains stock data in a simple format. Each line has the ticker symbol of the stock, the number of shares, and the price per share.
Using the import Statement
Python's import statement is a powerful tool that allows you to use code from other modules in your current program. It's like borrowing tools from other toolboxes. Let's practice using different ways to import code:
- First, we need to start the Python interpreter. The Python interpreter is a program that executes Python code. We'll use the following command to start it.
python3
- Now, let's import the
pcostmodule and see what happens. When we use theimportstatement, Python looks for thepcost.pyfile and makes the code inside it available for us to use.
import pcost
You should see the output 44671.15. This is the calculated cost of the portfolio from the portfolio.dat file. When the pcost module is imported, the code at the bottom of the pcost.py file runs automatically.
- Let's try calling the
portfolio_cost()function with a different portfolio file. We'll use thepcost.portfolio_cost()syntax to call the function from thepcostmodule.
pcost.portfolio_cost('portfolio2.dat')
The output should be 19908.75, which represents the total cost of the stocks in the second portfolio file.
- Now, let's import a specific class from the
stockmodule. Instead of importing the whole module, we can just import theStockclass using thefrom...importstatement.
from stock import Stock
- After importing the
Stockclass, we can create aStockobject. An object is an instance of a class. We'll create aStockobject with the nameGOOG, 100 shares, and a price of490.10. Then we'll print the name of the stock and calculate its cost using thecost()method.
s = Stock('GOOG', 100, 490.10)
print(s.name)
print(s.cost())
The output should be:
GOOG
49010.0
- Finally, when we're done using the Python interpreter, we can exit it using the
exit()function.
exit()
This lab has demonstrated two different ways to import Python code:
import module_name- This imports the entire module, making all the functions, classes, and variables in that module available for use.from module_name import specific_item- This imports only a specific item (like a class or a function) from the module, which can be useful if you only need a part of the module's functionality.
Understanding the Main Module in Python
In Python, when you run a script directly, it acts as the "main" module. Python has a special variable named __name__. When a file is executed directly, Python sets the value of __name__ to "__main__". This is different from when the file is imported as a module.
This feature is very useful because it allows you to write code that behaves differently depending on whether the file is run directly or imported. For example, you might want some code to run only when you execute the file as a script, but not when it's imported by another script.
Modifying pcost.py to Use the Main Module Pattern
Let's modify the pcost.py program to take advantage of this pattern.
- First, you need to open the
pcost.pyfile in the editor. You can use the following commands to navigate to the project directory and create the file if it doesn't exist:
cd ~/project
touch pcost.py
The cd command changes the current directory to the project directory in your home directory. The touch command creates a new file named pcost.py if it doesn't already exist.
- Now, modify the
pcost.pyfile to look like this:
## pcost.py
def portfolio_cost(filename):
total_cost = 0.0
with open(filename, 'r') as f:
for line in f:
fields = line.split()
try:
nshares = int(fields[1])
price = float(fields[2])
total_cost += nshares * price
except (ValueError, IndexError):
print(f"Couldn't parse: {line}")
return total_cost
## This code only runs when the file is executed as a script
if __name__ == "__main__":
total = portfolio_cost('portfolio.dat')
print(total)
The main change here is that we've wrapped the code at the end in an if __name__ == "__main__": condition. This means that the code inside this block will only run when the file is executed directly as a script, not when it's imported as a module.
- After making these changes, save the file and exit the editor.
Testing the Modified Module
Now, let's test our modified module in two different ways to see how it behaves.
- First, run the program directly as a script using the following command:
python3 pcost.py
You should see the output 44671.15, just like before. This is because when you run the script directly, the __name__ variable is set to "__main__", so the code inside the if __name__ == "__main__": block gets executed.
- Next, start the Python interpreter again and import the module:
python3
import pcost
This time, you won't see any output. When you import the module, the __name__ variable is set to "pcost" (the module name), not "__main__". So, the code inside the if __name__ == "__main__": block doesn't run.
- To verify that the
portfolio_costfunction still works, you can call it like this:
pcost.portfolio_cost('portfolio.dat')
The function should return 44671.15, which means it's working correctly.
- Finally, exit the Python interpreter using the following command:
exit()
This pattern is very useful when creating Python files that can be used both as importable modules and as standalone scripts. The code inside the if __name__ == "__main__": block only runs when the file is executed directly, not when it's imported as a module.
Creating Your Own Module
Now that you understand how to use existing modules, it's time to create a new module from scratch. A module in Python is a file containing Python definitions and statements. It allows you to organize your code into reusable and manageable pieces. By creating your own module, you can group related functions and variables together, making your code more modular and easier to maintain.
Creating a Report Module
Let's create a simple module for generating stock reports. This module will have functions to read a portfolio file and print a formatted report of the stocks in the portfolio.
- First, we need to create a new file named
report.py. To do this, we'll use the command line. Navigate to theprojectdirectory in your home directory and create the file using thetouchcommand.
cd ~/project
touch report.py
- Now, open the
report.pyfile in your preferred text editor and add the following code. This code defines two functions and a main block.
## report.py
def read_portfolio(filename):
"""
Read a stock portfolio file into a list of dictionaries with
keys: name, shares, price
"""
portfolio = []
with open(filename, 'r') as f:
for line in f:
fields = line.split()
try:
stock = {
'name': fields[0],
'shares': int(fields[1]),
'price': float(fields[2])
}
portfolio.append(stock)
except (ValueError, IndexError):
print(f"Couldn't parse: {line}")
return portfolio
def print_report(portfolio):
"""
Print a report showing the stock name, shares, price, and total value
"""
print("Name Shares Price Value")
print("-" * 40)
total_value = 0.0
for stock in portfolio:
value = stock['shares'] * stock['price']
total_value += value
print(f"{stock['name']:6s} {stock['shares']:9d} {stock['price']:9.2f} {value:9.2f}")
print("-" * 40)
print(f"Total Value: {total_value:16.2f}")
if __name__ == "__main__":
portfolio = read_portfolio('portfolio.dat')
print_report(portfolio)
The read_portfolio function reads a file containing stock information and returns a list of dictionaries, where each dictionary represents a stock with keys name, shares, and price. The print_report function takes a portfolio (a list of stock dictionaries) and prints a formatted report showing the stock name, number of shares, price, and total value. The main block at the end runs when the file is executed directly. It reads the portfolio file and prints the report.
- After adding the code, save and exit the editor.
Testing Your Module
Let's test our new module to make sure it works as expected.
- First, we'll run the script directly from the command line. This will execute the main block in the
report.pyfile.
python3 report.py
You should see a formatted report showing the portfolio stocks and their values. This report includes the stock name, number of shares, price, and total value, as well as the total value of the entire portfolio.
Name Shares Price Value
----------------------------------------
AA 100 32.20 3220.00
IBM 50 91.10 4555.00
CAT 150 83.44 12516.00
MSFT 200 51.23 10246.00
GE 95 40.37 3835.15
MSFT 50 65.10 3255.00
IBM 100 70.44 7044.00
----------------------------------------
Total Value: 44671.15
- Next, we'll use the module from the Python interpreter. Start the Python interpreter by running the
python3command in the terminal.
python3
Once the interpreter is running, we can import the report module and use its functions.
import report
portfolio = report.read_portfolio('portfolio.dat')
len(portfolio) ## Should return 7, the number of stocks
portfolio[0] ## First stock in the portfolio
The import report statement makes the functions and variables defined in the report.py file available in the current Python session. We then use the read_portfolio function to read the portfolio file and store the result in the portfolio variable. The len(portfolio) statement returns the number of stocks in the portfolio, and portfolio[0] returns the first stock in the portfolio.
You should see the following output:
7
{'name': 'AA', 'shares': 100, 'price': 32.2}
- Now, let's use the imported module to calculate the total cost of the portfolio ourselves. We'll iterate over the stocks in the portfolio and sum up the total value of each stock.
total = 0.0
for stock in portfolio:
total += stock['shares'] * stock['price']
print(total)
The output should be 44671.15, which is the same as the total value printed by the print_report function.
- Finally, let's create a custom report for a specific stock type. We'll filter the portfolio to include only the IBM stocks and then use the
print_reportfunction to print a report for those stocks.
ibm_stocks = [stock for stock in portfolio if stock['name'] == 'IBM']
report.print_report(ibm_stocks)
This should print a report showing only the IBM stocks and their values.
Name Shares Price Value
----------------------------------------
IBM 50 91.10 4555.00
IBM 100 70.44 7044.00
----------------------------------------
Total Value: 11599.00
- When you're done testing, exit the Python interpreter by running the
exit()command.
exit()
You've now successfully created and used your own Python module, combining both functions and a main block that only runs when the file is executed directly. This modular approach to programming allows you to reuse code and make your projects more organized and maintainable.
Summary
In this lab, you have learned the fundamental concepts of Python modules and how to use them for code organization. Modules are Python files with reusable code, and the import statement enables you to utilize code from other modules in your program. The if __name__ == "__main__" pattern allows files to function as both importable modules and standalone scripts.
These concepts are crucial for writing maintainable Python code, especially when developing larger applications. As you continue learning Python, remember that modules help group related code, importing specific items keeps the namespace clean, and the main module pattern is a best practice. Applying these techniques will make your code more organized, maintainable, and reusable.