- Use Python's import system to modularize and reuse code efficiently.
- Apply File Input/Output (I/O) to persist and retrieve data from external files.
- Handle file access safely with
with open()
and exception handling. - Structure Python applications using standard configuration and modularization techniques.
In Python, separating code into modules and working with external files are essential for building real-world applications. This lesson will cover:
- Importing built-in or custom modules.
- Writing logs to an external file.
- Searching and filtering logs from a file.
- Preventing application crashes using exception handling.
Let’s consider a user activity tracking application where logs need to be written and retrieved from a file. The application currently supports:
- Writing hardcoded messages to the console.
However, it lacks:
- Persisting actions to a file for record-keeping.
- Filtering user activity logs by keywords.
- Handling errors like missing log files gracefully.
To solve these issues, we will:
- Write logs to a file using
with open()
and thedatetime
module. - Read logs from the file and filter based on keywords.
- Handle missing files using a
try-except
block. - Organize logic using importable Python modules.
To get started, clone the repository and install any necessary requirements:
git clone <repo-url>
cd course-7-module-6-imports-and-file-io
pipenv install
pipenv shell
Now, let's define the structure of our logger module.
We will use the datetime
module to timestamp actions and with open()
to append to a file.
from datetime import datetime
def log_action(action, log_file="data/user_logs.txt"):
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
with open(log_file, "a") as file:
file.write(f"[{timestamp}] {action}\n")
- Appends each action to
user_logs.txt
with a timestamp. - Uses
with open()
for automatic file closure.
We can retrieve only the lines that match a search term.
def search_logs(keyword, log_file="data/user_logs.txt"):
try:
with open(log_file, "r") as file:
matches = [line.strip() for line in file if keyword.lower() in line.lower()]
if matches:
print("\nFiltered Logs:")
for match in matches:
print(match)
else:
print("No matching log entries found.")
except FileNotFoundError:
print("Log file not found.")
- Safely opens and reads the file.
- Filters matching lines using a list comprehension.
- Gracefully handles missing files.
We are currently using argparse
to allow users to log actions or search logs from the terminal.
import argparse
from logger import log_action, search_logs
def main():
parser = argparse.ArgumentParser(description="User Log Management CLI Tool")
subparsers = parser.add_subparsers(dest="command")
log_parser = subparsers.add_parser("log", help="Log a user action")
log_parser.add_argument("action", type=str, help="The action to log")
search_parser = subparsers.add_parser("search", help="Search logs by keyword")
search_parser.add_argument("keyword", type=str, help="Keyword to filter logs")
args = parser.parse_args()
if args.command == "log":
log_action(args.action)
elif args.command == "search":
search_logs(args.keyword)
else:
parser.print_help()
if __name__ == "__main__":
main()
If you run python lib/main.py
, you should see a list of the commands you can run:
- log
- search
Try running these in the terminal, such as:
python lib/main.py log "testing code"
python lib/main.py log "deploying code"
python lib/main.py log "patching code"
If you search for 'code'you should see all of these printed to the terminal:
python lib/main.py search "code"
If you search for 'deploying' or 'testing' however, you will only see the one that includes that word.
You should also be able to view your logs in data/user_logs.txt
.
- Always use
with open()
to safely handle files and automatically close them. - Use
try-except
blocks to catch errors such as missing files or permission issues. - Keep import statements at the top of your Python files.
- Separate logic into reusable modules to improve organization and readability.
- Avoid hardcoding file paths—use variables or configs when possible.
By mastering Imports and File I/O, developers can:
- Structure Python applications for maintainability and reuse.
- Persist data through external files safely and efficiently.
- Handle errors without crashing the application.
- Build scalable CLI tools that integrate clean code and modular design.
These foundational skills are essential for working with real-world data and building production-level Python applications.