Python Modules and Packages for Beginners
What’s the difference between a module and a package?
A module is a .py file containing Python code that you can reuse. A package is a directory containing modules and an __init__.py file (or namespace package). The key difference is structural: modules are files, packages are directories that organize multiple modules together.
Python modules and packages solve the same problem as your codebase grows: code becomes harder to manage if you dump everything in one file. Modules and packages let you split logic across files, import what you need, and keep things organized. The official Python modules tutorial is the authoritative reference for everything below.
Importing modules
The import keyword loads a module into your code. Let’s start with Python’s built-in random module, which generates random numbers.
import random
x = random.random()
print(x)
Output:
0.33510690081074157
When you import a module, you access its functions using module.function() syntax. The module name becomes a variable in your namespace.
You can also import specific functions using from:
from random import choice
x = choice([1, 2, 3, 4, 5])
print(x)
Output:
3
With from, you call the function directly without the module name prefix. This is cleaner when you only need one or two functions, but it makes it less obvious where the function comes from.
You can rename a module on import using as:
import random as rd
x = rd.random()
print(x)
Output:
0.7814491472746951
Aliasing is useful when a module name is long or conflicts with a variable you’re using. PEP 8 discourages from module import * because it pollutes your namespace with all the module’s names at once.
Writing your own modules
A module is just a .py file. Create a file called mod.py with a function inside:
def say_hello():
return "Hello World"
Now, in a separate file, import and use it:
import mod
x = mod.say_hello()
print(x)
Output:
Hello World
That’s it. Python found mod.py in the same directory and loaded it. You can add multiple functions to a module and import whichever ones you need.
A module can hold functions, variables, classes, or anything else:
def say_hello():
return "Hello World"
def add_numbers(x, y):
return x + y
numbers = [1, 2, 3, 4, 5]
greeting = "Hello"
Import specific items from this module:
from mod import say_hello, add_numbers, numbers
print(say_hello())
print(add_numbers(10, 20))
print(numbers)
Output:
Hello World
30
[1, 2, 3, 4, 5]
When importing multiple items, list them in the from import statement separated by commas. A module is just a .py file, so once you’re organizing code across files, you’ll also want to know how Python reads and writes files directly.
Packages: organizing modules
As your project grows, a flat collection of .py files becomes messy. Packages let you group related modules in directories.
Create a package structure like this:
my_project/
main.py
package_one/
__init__.py
module_1.py
module_2.py
package_two/
__init__.py
module_3.py
The __init__.py file tells Python “treat this directory as a package.” In Python 3, it can be empty. If you want initialization code to run when the package is imported, put it in __init__.py.
In package_one/module_1.py:
def greet():
return "Hello from package_one"
In package_one/module_2.py:
def add(x, y):
return x + y
From main.py, import modules from both packages:
from package_one import module_1, module_2
from package_two import module_3
print(module_1.greet())
print(module_2.add(10, 20))
Output:
Hello from package_one
30
The dotted import path mirrors the directory structure. This is much cleaner than having 20 modules floating around in one folder.
Namespace packages
Python 3.3+ introduced namespace packages (PEP 420), which let directories act as packages without an __init__.py file. This is an advanced feature, but it’s good to know it exists.
If you omit __init__.py, Python still treats the directory as a namespace package. The main difference is that namespace packages can be split across multiple locations on your file system, which is useful for large projects or plugins. For most code, you’ll want a regular package with an __init__.py.
Using __name__ == '__main__'
When you run a .py file directly, Python sets its __name__ variable to '__main__'. When you import it, __name__ is the module name instead. This pattern lets code behave differently depending on how it’s run.
def greet():
print("Hello from the module")
if __name__ == '__main__':
greet()
print("This runs only when the file is executed directly")
If you run this file, it prints both lines. If you import it in another file, only greet() runs when you call it explicitly.
This is a standard Python convention for making reusable modules that can also function as standalone scripts.
When do you actually use modules and packages?
Early on, a single script is fine. Once you hit a few hundred lines or start sharing code between projects, break it into modules. Packages become necessary when you have multiple related modules.
The rule of thumb: if you’re copy-pasting functions between files, extract them into a module. If you’re managing a collection of related modules, wrap them in a package.
What structure does your current project use, and are there modules you find yourself reusing across multiple scripts?