Python functions, modules, packages and virtual environments
In short: Functions wrap a task in a named, reusable block with inputs and a return value. Modules and packages organise functions across files. Virtual environments keep each project’s libraries separate so scripts keep working when you install something new.
Why organise your code
A first script is often one long file that runs top to bottom. That works until you copy the same twenty lines into a third script and then have to fix a bug in all three. Functions and modules let you write something once, test it once and reuse it everywhere.
Writing functions
A function is defined with def, takes parameters, and usually hands a result back with return. Give it a name that says what it does, and a short docstring. Type hints (such as vlan_id: int) are optional but help editors and readers.
def vlan_config(vlan_id: int, name: str, shutdown: bool = False) -> list[str]:
"""Return the config lines for one VLAN."""
lines = [f"vlan {vlan_id}", f" name {name}"]
if shutdown:
lines.append(" shutdown")
return lines
for line in vlan_config(20, "USERS"):
print(line)
print(vlan_config(99, "UNUSED", shutdown=True))
shutdown=False is a default argument: callers can leave it out. Passing shutdown=True by name (a keyword argument) makes the call easy to read. A good function does one job, returns data rather than printing it, and does not depend on hidden global variables.
Tip: never use a list or dict as a default value (def f(items=[])). The same object is shared between calls. Use None and create the list inside the function.
Modules and packages
Any .py file is a module. Put helper functions in, say, netutils.py and import them from other scripts. A package is a folder of modules. The guard if __name__ == "__main__": lets a file work both as a script and as an importable module.
# netutils.py
def is_valid_vlan(vlan_id: int) -> bool:
return 1 <= vlan_id <= 4094
if __name__ == "__main__":
print(is_valid_vlan(20))
# audit.py
from netutils import is_valid_vlan
for v in [1, 20, 5000]:
print(v, is_valid_vlan(v))
The standard library already includes many useful modules: ipaddress, json, csv, re, logging, getpass and socket. Check there before installing anything.
pip and virtual environments
pip installs third-party packages from the Python Package Index. A virtual environment (venv) is a private folder of packages for one project, so upgrading Netmiko for one tool does not break another. It also means you do not need administrator rights to install libraries.
python3 -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install netmiko pyyaml
pip freeze > requirements.txt
# later, on another machine:
pip install -r requirements.txt
- Do not commit the
.venvfolder to Git; commitrequirements.txtinstead. - Install only packages you need from names you have checked. Typo-squatted packages with names close to popular ones have been used to deliver malware.
- Pin versions for tools that matter, and update them deliberately.
Putting it together at work
A tidy automation project might have a netutils package of tested helpers, a few short scripts that import them, a requirements.txt, and a README explaining how to run it. Colleagues can then clone it, create a venv and get the same result. That reproducibility is what turns a personal script into a team tool.
Practice
What is the difference between printing a result inside a function and returning it?
Why use a virtual environment for each project?
What does if __name__ == "__main__": do?
Key takeaways
- Functions wrap one job, take parameters and return a value.
- Avoid mutable default arguments; use None instead.
- Modules are .py files; packages are folders of modules.
- Use a venv per project and record dependencies in requirements.txt.
- Check package names carefully before installing them.
Original content written by Mohamed Fayas for FM TecHub. © 2026 FM TecHub. You're welcome to share a link to this page; please don't copy the text elsewhere without permission.