Unit 4 · Modules and File Handling
User-Defined Modules
Learn how to create your own Python modules, understand the __name__ variable, and organize code using packages and the __init__.py file.
Introduction
While Python's standard library provides many built-in modules, you will often need to create your own modules to organize code in larger projects. A user-defined module is simply any Python file whose functions, classes, and variables can be imported into other files.
This chapter covers how to create modules, use the special __name__ variable, and organize modules into packages for complex projects.
University Definition
A user-defined module is a Python file (.py) created by the programmer that contains reusable functions, classes, and variables. Any Python file can serve as a module when imported by another file. The __name__ variable helps distinguish whether a file is being run directly or imported as a module.
Table of Contents
Creating a User-Defined Module
Creating a module is as simple as writing a Python file. There is no special syntax or declaration required.
# File: mymath.py (This is our user-defined module)
def add(a, b):
"""Add two numbers"""
return a + b
def subtract(a, b):
"""Subtract b from a"""
return a - b
def multiply(a, b):
"""Multiply two numbers"""
return a * b
def divide(a, b):
"""Divide a by b"""
if b == 0:
return "Error: Division by zero"
return a / b
PI = 3.14159
VERSION = "1.0"
Real-life Analogy: Think of creating a module like writing a recipe book. Each recipe (function) can be used by anyone who has the book (imports the module). You can also include constants like ingredient ratios (module variables).
The __name__ Variable and "__main__"
University Definition
Every Python module has a special built-in variable called __name__. When a file is run directly, __name__ is set to "__main__". When a file is imported as a module, __name__ is set to the module's name. This allows code to execute only when the file is run directly, not when imported.
# File: mymath.py
def add(a, b):
return a + b
def subtract(a, b):
return a - b
# This code runs ONLY when mymath.py is executed directly
if __name__ == "__main__":
print("Testing mymath module...")
print("3 + 5 =", add(3, 5))
print("10 - 4 =", subtract(10, 4))
print("All tests passed!")
# This output appears only when running: python mymath.py
# It does NOT appear when importing: import mymath
University Exam Tip
The if __name__ == "__main__": pattern is one of the most commonly asked questions. It ensures that test code or demo code in a module runs only when the file is executed directly, not when it is imported by another module.
How it Works
When you run python mymath.py
__name__ = "__main__"
The code inside if __name__ == "__main__": executes.
When another file does import mymath
__name__ = "mymath"
The code inside if __name__ == "__main__": does NOT execute.
Importing User-Defined Modules
Importing your own modules works exactly the same as importing built-in modules. The module file must be in the same directory as the importing script, or in a directory on the Python path.
# File: main.py (in the same directory as mymath.py) # Method 1: Import the whole module import mymath print(mymath.add(3, 5)) # 8 print(mymath.PI) # 3.14159 # Method 2: Import specific functions from mymath import add, multiply print(add(10, 20)) # 30 print(multiply(4, 5)) # 20 # Method 3: Import with alias from mymath import subtract as sub print(sub(100, 50)) # 50 # Method 4: Import everything (not recommended) from mymath import * print(add(1, 2)) # 3
Module vs Script
| Feature | Module | Script |
|---|---|---|
| Purpose | Reusability — imported by other files | Execution — run directly |
| __name__ value | Module name (e.g., "mymath") | "__main__" |
| Contains | Functions, classes, constants | Main logic, user interaction |
| Example | mymath.py, utils.py | main.py, app.py |
Packages and __init__.py
A package is a directory containing multiple Python modules along with a special __init__.py file. Packages allow you to organize related modules into subdirectories.
# Project structure:
# myproject/
# main.py
# mypackage/
# __init__.py
# arithmetic.py
# string_utils.py
# mypackage/__init__.py
from .arithmetic import add, subtract
from .string_utils import capitalize_words
# mypackage/arithmetic.py
def add(a, b):
return a + b
def subtract(a, b):
return a - b
# mypackage/string_utils.py
def capitalize_words(sentence):
return sentence.title()
# main.py
from mypackage import add, capitalize_words
print(add(3, 5)) # 8
print(capitalize_words("hello world")) # Hello World
University Exam Tip
The __init__.py file can be empty (it just marks the directory as a package) or it can contain initialization code and imports. In Python 3.3+, implicit namespace packages exist, but __init__.py is still the standard practice.
Relative Imports
# Within a package, use relative imports: from . import module_name # Import from current directory from .sibling import function_name # Import from sibling module from .. import parent_module # Import from parent package from ..other_pkg import something # Import from parent's sibling
Complete Example
# File: stringutils.py (user-defined module)
def reverse_string(s):
"""Reverse a string"""
return s[::-1]
def count_vowels(s):
"""Count vowels in a string"""
return sum(1 for c in s.lower() if c in "aeiou")
def is_palindrome(s):
"""Check if string is palindrome"""
clean = s.lower().replace(" ", "")
return clean == clean[::-1]
if __name__ == "__main__":
# Test code — only runs when executed directly
print("Testing stringutils module:")
print(reverse_string("Python")) # nohtyP
print(count_vowels("Hello World")) # 3
print(is_palindrome("Racecar")) # True
print(is_palindrome("Hello")) # False
# File: main.py
from stringutils import reverse_string, is_palindrome
print(reverse_string("University")) # ytisrevinU
print(is_palindrome("Madam")) # True
Key Points
Any .py file can serve as a user-defined module.
__name__ is "__main__" when run directly, module name when imported.
Use if __name__ == "__main__": to write test code in modules.
A package is a directory with __init__.py and multiple module files.
__init__.py can be empty or contain package-level imports.
Relative imports use . (current) and .. (parent) notation.
The module file must be on the Python path to be importable.
User-defined modules are imported the same way as built-in modules.
Practice Questions
Q1: What is a user-defined module?
Answer: A user-defined module is any Python file (.py) created by the programmer that contains functions, classes, and variables that can be imported and reused in other Python files.
Q2: Explain the significance of if __name__ == "__main__":
Answer: This ensures code only runs when the file is executed directly, not when imported as a module. It allows a file to be both a reusable module and an executable script.
Q3: What is a package in Python?
Answer: A package is a directory containing multiple Python modules and an __init__.py file that marks it as a Python package.
Q4: What is the role of __init__.py?
Answer: __init__.py marks a directory as a Python package and can optionally import specific names from submodules to control the package's public API.
Q5: How is a module different from a script?
Answer: A module is designed for reusability and is imported by other files. A script is designed to be run directly and contains the main program logic.
Summary
Any .py file can be used as a user-defined module.
__name__ == "__main__" separates module code from test code.
Packages group related modules into directories with __init__.py.
Relative imports (., ..) work within packages.
User-defined modules are imported using the same syntax as built-in modules.
The module must be on the Python path (same directory or added to sys.path).