This article presents 30 coding exercises that teach you to work with Python’s os and sys modules — the foundation of any practical scripting or automation work. Topics covered include file and directory operations such as creating, renaming, deleting, and traversing directory trees; reading and setting environment variables; handling command-line arguments with sys.argv; platform detection; managing the module search path with sys.path; and controlling interpreter behaviour through recursion limits and exit codes.
Each coding challenge includes a Practice Problem, Hint, Solution code, and detailed Explanation, ensuring you don’t just copy code, but genuinely practice and understand how and why it works.
- All solutions have been fully tested on Python 3.
- Use our Online Code Editor to solve these exercises in real time.
- Also, Solve Python Exercises: 29 topic-wise exercises with over 800+ coding questions
Let us know if you have any alternative solutions. It will help other developers.
+ Table of Contents (30 Exercises)
Table of contents
- Exercise 1: Print Current Directory
- Exercise 2: List Directory Contents
- Exercise 3: Create a Directory
- Exercise 4: Create Nested Directories
- Exercise 5: Rename a File
- Exercise 6: Delete a File
- Exercise 7: Delete a Directory Tree
- Exercise 8: Check Path Existence
- Exercise 9: Split File Extension
- Exercise 10: Get File Size
- Exercise 11: Read an Environment Variable
- Exercise 12: Set an Environment Variable
- Exercise 13: List All Environment Variables
- Exercise 14: Get Current Process ID
- Exercise 15: Run a Shell Command
- Exercise 16: Walk a Directory Tree
- Exercise 17: Join Paths Safely
- Exercise 18: Get Absolute Path
- Exercise 19: Print Python Version
- Exercise 20: Read Command-Line Arguments
- Exercise 21: Exit a Program
- Exercise 22: Get Platform Info
- Exercise 23: Inspect sys.path
- Exercise 24: Add to sys.path
- Exercise 25: Get Recursion Limit
- Exercise 26: Change Recursion Limit
- Exercise 27: Script Info Logger
- Exercise 28: Directory Size Calculator
- Exercise 29: Environment Config Loader
- Exercise 30: Recursive File Finder
Exercise 1: Print Current Directory
Problem Statement: Write a Python program that prints the current working directory to the console.
Purpose: This exercise introduces the os module and its most fundamental function. Knowing how to retrieve the current working directory is a foundational skill for file I/O operations, path construction, and building scripts that need to locate resources relative to where they run.
Given Input: No input required. The function reads the environment directly.
Expected Output: /home/user/projects (the actual path will vary based on your system)
▼ Hint
- Import the
osmodule at the top of your script. - Use
os.getcwd()to retrieve the current working directory as a string. - Pass the result directly to
print().
▼ Solution & Explanation
Explanation:
import os: Loads Python’s built-inosmodule, which provides functions for interacting with the operating system.os.getcwd(): Stands for “get current working directory.” It returns an absolute path string representing the directory from which the script is being run.print("Current Directory:", cwd): Displays the path in a readable format. The output will differ depending on your OS and the folder where the script is executed.
Exercise 2: List Directory Contents
Problem Statement: Write a Python program that lists all files and folders in a given directory path.
Purpose: This exercise teaches you to inspect a directory’s contents programmatically. It is a core skill for building file managers, automation scripts, batch processors, and any tool that needs to discover what files are available at runtime.
Given Input: path = "." (the current directory)
Expected Output: A printed list of all file and folder names in the specified directory (output varies by system).
▼ Hint
- Use
os.listdir(path)to get a list of all entries in the given directory. - Iterate over the returned list with a
forloop and print each item. - The list includes both files and subdirectories, but does not recurse into subdirectories.
▼ Solution & Explanation
Explanation:
os.listdir(path): Returns a Python list of strings, where each string is the name of a file or subfolder insidepath. It does not include.or..entries.for item in contents: Iterates over each entry in the list returned bylistdir(), printing one name per line.- Note: The entries are not sorted by default. Wrap the call in
sorted()if alphabetical order is needed:sorted(os.listdir(path)).
Exercise 3: Create a Directory
Problem Statement: Write a Python program that creates a new folder called test_folder in the current working directory, only if it does not already exist.
Purpose: Creating directories programmatically is essential for setting up output folders, organising generated files, and building scripts that prepare a workspace before writing data. Checking for existence first prevents crashes from duplicate creation.
Given Input: folder_name = "test_folder"
Expected Output: Folder 'test_folder' created successfully. or Folder 'test_folder' already exists.
▼ Hint
- Use
os.path.exists(folder_name)to check if the folder already exists before creating it. - If it does not exist, call
os.mkdir(folder_name)to create it. - Use an
if/elseblock to print the appropriate message in each case.
▼ Solution & Explanation
Explanation:
os.path.exists(folder_name): ReturnsTrueif the given path (file or folder) already exists on disk, preventing aFileExistsErrorwhen callingmkdir().os.mkdir(folder_name): Creates a single new directory at the specified path. It will raise aFileNotFoundErrorif any intermediate parent directories are missing – useos.makedirs()for nested paths instead.- f-strings: The
f"..."syntax is used for clean, readable string formatting with the variable embedded directly.
Exercise 4: Create Nested Directories
Problem Statement: Write a Python program that creates a nested directory structure a/b/c in the current working directory, even if some or all of the parent directories do not yet exist.
Purpose: Real-world scripts frequently need to create deep folder hierarchies in a single step – for example, when organising output by date (logs/2025/06/10) or project structure. os.makedirs() handles this without requiring manual creation of each level.
Given Input: nested_path = "a/b/c"
Expected Output: Nested directories 'a/b/c' created successfully.
▼ Hint
- Use
os.makedirs(path)instead ofos.mkdir()to create all intermediate directories in one call. - Pass
exist_ok=Trueas a keyword argument to avoid an error if the directory already exists. - Use
os.path.join()to build the path safely across different operating systems if needed.
▼ Solution & Explanation
Explanation:
os.path.join("a", "b", "c"): Constructs the path using the correct separator for the current OS (/on Unix,\on Windows), making the script portable.os.makedirs(nested_path, exist_ok=True): Creates all directories in the path recursively. Theexist_ok=Trueargument suppresses theFileExistsErrorthat would otherwise be raised if any part of the path already exists.- Difference from
os.mkdir():mkdir()can only create one level at a time and fails if a parent is missing.makedirs()handles the entire chain in a single call.
Exercise 5: Rename a File
Problem Statement: Write a Python program that renames a file called old.txt to new.txt in the current directory, with a check to confirm the source file exists before attempting the rename.
Purpose: Renaming files is a common task in file management scripts, data pipelines, and backup utilities. This exercise reinforces safe file handling by combining existence checks with the rename operation, preventing runtime errors on missing files.
Given Input: A file named old.txt must exist in the current directory.
Expected Output: Renamed 'old.txt' to 'new.txt' successfully. or Source file 'old.txt' does not exist.
▼ Hint
- Use
os.path.exists("old.txt")to verify the file is present before renaming. - Call
os.rename(src, dst)wheresrcis the current filename anddstis the new filename. - To test this, create
old.txtfirst usingopen("old.txt", "w").close()at the top of your script.
▼ Solution & Explanation
Explanation:
open(src, "w").close(): Creates an empty file for testing. The"w"mode opens the file for writing, and.close()immediately closes it, leaving a zero-byte file on disk.os.path.exists(src): Guards against aFileNotFoundErrorby confirming the source file is present before the rename is attempted.os.rename(src, dst): Renames (or moves, if paths differ) the file atomically on most operating systems. Ifdstalready exists, it will be silently overwritten on Unix but raise an error on Windows.
Exercise 6: Delete a File
Problem Statement: Write a Python program that deletes a file called temp.txt from the current directory, but only after verifying that the file actually exists.
Purpose: Safe file deletion is a critical skill in automation and cleanup scripts. Blindly calling a delete function without checking for existence will raise an exception and halt your program. This exercise builds the habit of defensive file operations.
Given Input: A file named temp.txt (created in the script for testing).
Expected Output: File 'temp.txt' deleted successfully. or File 'temp.txt' not found.
▼ Hint
- Use
os.path.exists(filename)to check if the file is present before deletion. - Call
os.remove(filename)to delete the file. This works only on files, not directories. - To delete a directory, use
os.rmdir()(empty only) orshutil.rmtree()(non-empty).
▼ Solution & Explanation
Explanation:
with open(filename, "w") as f: Creates the test file using a context manager, which automatically closes the file handle when the block exits – a best practice over manual.close()calls.os.path.exists(filename): ReturnsTrueif the path points to an existing file or directory, letting you branch safely before the destructive operation.os.remove(filename): Permanently deletes the specified file. It raisesIsADirectoryErrorif the path points to a folder, so use the appropriate function based on what you are deleting.
Exercise 7: Delete a Directory Tree
Problem Statement: Write a Python program that creates a nested directory structure cleanup/a/b, adds a dummy file inside it, then removes the entire tree including all contents.
Purpose: Removing a directory and all of its contents is a frequent requirement in test teardown, temporary file cleanup, and build scripts. This exercise demonstrates the difference between os.rmdir() (empty directories only) and shutil.rmtree() (recursive deletion).
Given Input: Directory tree cleanup/a/b with a file cleanup/a/b/note.txt inside (created in the script).
Expected Output: Directory tree 'cleanup' removed successfully.
▼ Hint
- Use
os.makedirs()to create the nested directory andopen()to create a dummy file inside it. - Import
shutiland useshutil.rmtree(path)to recursively delete the entire directory including all files and subdirectories. - Use
os.path.exists()before callingrmtree()to avoid errors if the directory is already gone.
▼ Solution & Explanation
Explanation:
os.makedirs(nested_path, exist_ok=True): Creates the fullcleanup/a/bpath in one call. Theexist_ok=Trueparameter prevents errors if the path was already created from a previous run.shutil.rmtree(base_dir): Recursively deletes the entire directory tree rooted atbase_dir, including all subdirectories and files.os.rmdir()would fail here because the directory is not empty.import shutil: Theshutil(shell utilities) module complementsoswith higher-level file operations like recursive copy and recursive delete, which theosmodule alone does not support.
Exercise 8: Check Path Existence
Problem Statement: Write a Python program that checks whether a given file or directory path exists on the system and prints a descriptive message indicating the result.
Purpose: Before performing any file operation – reading, writing, deleting, or renaming – it is good practice to verify that the target path actually exists. This exercise builds the habit of defensive path checking, which prevents FileNotFoundError crashes in production scripts.
Given Input: path = "sample.txt" (created in the script for testing)
Expected Output: Path 'sample.txt' exists. or Path 'sample.txt' does not exist.
▼ Hint
- Use
os.path.exists(path)to check for either a file or a directory at the given path. - For more specific checks, use
os.path.isfile(path)to confirm it is a file, oros.path.isdir(path)to confirm it is a directory. - Use an
if/elseblock to print the appropriate message for each case.
▼ Solution & Explanation
Explanation:
os.path.exists(path): ReturnsTrueif the path points to an existing file or directory, andFalseotherwise. It also returnsFalsefor broken symbolic links.os.path.isfile(path): A more targeted check that returnsTrueonly if the path exists and is a regular file – useful when you need to rule out directories.os.path.isdir(path): ReturnsTrueonly if the path exists and is a directory. Combining all three checks lets you build robust path-validation logic in larger scripts.
Exercise 9: Split File Extension
Problem Statement: Write a Python program that takes a filename string and extracts both the base name and the file extension separately.
Purpose: Parsing filenames is a routine task in file processing pipelines – for example, when filtering files by type, renaming files while preserving extensions, or routing files to different handlers based on format. This exercise introduces the clean, OS-aware way to split a filename.
Given Input: filename = "report_2025.pdf"
Expected Output: Base: report_2025 and Extension: .pdf
▼ Hint
- Use
os.path.splitext(filename)which returns a tuple of(root, ext). - The extension includes the leading dot, for example
.pdfnotpdf. - You can unpack the result directly:
base, ext = os.path.splitext(filename).
▼ Solution & Explanation
Explanation:
os.path.splitext(filename): Splits the filename at the last dot and returns a two-element tuple: the root name and the extension (including the dot). For"report_2025.pdf"it returns('report_2025', '.pdf').base, ext = ...: Tuple unpacking assigns both parts to separate variables in a single, readable line rather than using index access like[0]and[1].- Edge cases: For a file with no extension such as
"README",extwill be an empty string"". For dotfiles like".gitignore", the entire name is treated as the root with an empty extension.
Exercise 10: Get File Size
Problem Statement: Write a Python program that creates a file with some content and then prints its size in bytes.
Purpose: Checking file size is useful in scripts that enforce size limits, monitor disk usage, validate that a file was written correctly, or decide whether to process a file. This exercise shows how to retrieve file metadata without opening the file itself.
Given Input: A file named data.txt containing the text Hello, Python! (created in the script).
Expected Output: File size: 14 bytes
▼ Hint
- Use
os.path.getsize(filepath)to retrieve the file size in bytes as an integer. - Make sure the file exists before calling
getsize(), otherwise it raises aFileNotFoundError. - To convert bytes to kilobytes, divide the result by
1024.
▼ Solution & Explanation
Explanation:
os.path.getsize(filepath): Returns the size of the file at the given path in bytes as an integer. It reads from the filesystem metadata and does not need to open or read the file contents.- File size vs character count: The string
"Hello, Python!"has 14 characters. In a UTF-8 encoded file each ASCII character occupies 1 byte, so the size is 14 bytes. Files with Unicode characters may have a larger byte size than their character count. - Practical extension: To display a human-readable size, divide by
1024for KB,1024 ** 2for MB, and so on, then format withf"{size / 1024:.2f} KB".
Exercise 11: Read an Environment Variable
Problem Statement: Write a Python program that reads the system’s PATH environment variable and prints its value. If the variable is not found, print a default fallback message.
Purpose: Environment variables are the standard way to pass configuration into programs without hardcoding values. Reading them is essential for writing scripts that behave differently across development, staging, and production environments, or that respect system-level settings.
Given Input: No input required. The value is read from the operating system environment.
Expected Output: The value of the PATH variable (a long colon-separated string on Unix or semicolon-separated on Windows).
▼ Hint
- Use
os.environ.get("PATH")to safely read the variable. Unlikeos.environ["PATH"], the.get()method returnsNoneinstead of raising aKeyErrorif the variable is missing. - Pass a second argument to
.get()as the fallback value:os.environ.get("PATH", "Not set"). - On Unix systems, individual directories in
PATHare separated by:. Use.split(":")to print each directory on its own line.
▼ Solution & Explanation
Explanation:
os.environ: A dictionary-like object that maps environment variable names to their string values. It reflects the environment at the time the Python interpreter started.os.environ.get("PATH", "PATH variable not set"): The.get(key, default)pattern is the safest way to read an environment variable. IfPATHis not defined, the second argument is returned instead of raising an exception.- Preferred over
os.environ["PATH"]: Direct key access raises aKeyErrorif the variable is absent. Using.get()keeps the script robust, especially for optional or custom environment variables that may not always be set.
Exercise 12: Set an Environment Variable
Problem Statement: Write a Python program that sets a custom environment variable called APP_MODE to the value development, then reads it back and prints it.
Purpose: Setting environment variables at runtime lets scripts configure themselves or communicate settings to child processes. This is a common pattern in web frameworks, CLI tools, and test harnesses that need to switch between modes without changing source code.
Given Input: No external input. The variable is defined within the script.
Expected Output: APP_MODE is set to: development
▼ Hint
- Set the variable using
os.environ["APP_MODE"] = "development". - Read it back with
os.environ.get("APP_MODE")to confirm it was stored correctly. - Remember that changes made to
os.environaffect only the current process and its children – they do not persist in the shell after the script exits.
▼ Solution & Explanation
Explanation:
os.environ["APP_MODE"] = "development": Adds or updates the keyAPP_MODEin the process environment. Both the key and value must be strings – passing an integer will raise aTypeError.os.environ.get("APP_MODE", "not set"): Reads the variable back with a safe fallback. Because we just set it, this will return"development".- Scope of the change: The assignment modifies
os.environonly for the lifetime of the current Python process. Any child processes launched viasubprocesswill inherit the updated environment, but the parent shell remains unchanged once the script exits.
Exercise 13: List All Environment Variables
Problem Statement: Write a Python program that prints all currently available environment variables, displaying each name and its value on a separate line in a readable format.
Purpose: Inspecting the full environment is helpful when debugging configuration issues, auditing what a script can see at runtime, or exploring a new system. This exercise also reinforces how to iterate over a dictionary-like object.
Given Input: No input required. The data is read from the live process environment.
Expected Output: A list of all environment variable names and values, one per line (output varies by system).
▼ Hint
os.environbehaves like a regular Python dictionary, so you can call.items()on it to get key-value pairs.- Use a
for key, value in os.environ.items():loop to iterate and print each pair. - Wrap the iteration in
sorted(os.environ.items())to print variables in alphabetical order for easier reading.
▼ Solution & Explanation
Explanation:
os.environ.items(): Returns all key-value pairs from the environment as an iterable of tuples, identical in behaviour to calling.items()on a standard Pythondict.sorted(...): Wrapping the iterable insorted()arranges the variables alphabetically by key, making the output easier to scan compared to the arbitrary insertion order of the raw environment.- Privacy note: The environment may contain sensitive values such as API keys or passwords. Be careful not to log or display the full environment output in shared or production contexts.
Exercise 14: Get Current Process ID
Problem Statement: Write a Python program that retrieves and prints the process ID (PID) of the currently running Python script.
Purpose: The process ID uniquely identifies a running program on the operating system. It is useful in logging, debugging multi-process applications, creating unique temporary filenames, and communicating between processes. This exercise introduces basic process introspection using the os module.
Given Input: No input required. The PID is provided by the operating system.
Expected Output: Current Process ID: 12345 (the actual number will vary each time the script runs)
▼ Hint
- Use
os.getpid()to retrieve the PID of the current process as an integer. - Use
os.getppid()to also retrieve the parent process ID as a bonus exercise.
▼ Solution & Explanation
Explanation:
os.getpid(): Returns the integer process ID assigned by the OS to the current Python interpreter process. Each time the script runs, the OS assigns a different PID.os.getppid(): Returns the PID of the parent process – typically the shell or terminal that launched the script. This is useful when working with process trees or verifying that a subprocess was spawned by the expected parent.- Practical use: PIDs are commonly embedded in log messages (
f"[PID {os.getpid()}] Task started") to distinguish output from concurrent processes running the same script in parallel.
Exercise 15: Run a Shell Command
Problem Statement: Write a Python program that runs a shell command using os.system() and prints the exit code returned by the command.
Purpose: Running shell commands from within Python is a common requirement in automation scripts, build tools, and system administration utilities. This exercise introduces os.system() as the simplest way to invoke a command and inspect whether it succeeded or failed.
Given Input: No external input required. The command is hardcoded in the script.
Expected Output: The output of the shell command printed to the terminal, followed by Exit code: 0
▼ Hint
- Use
os.system("command")where the argument is a shell command string such as"ls"on Unix or"dir"on Windows. os.system()returns the exit code of the command:0means success, any non-zero value indicates an error.- To make the script cross-platform, detect the OS first using
sys.platformand choose the appropriate command accordingly.
▼ Solution & Explanation
Explanation:
os.system(command): Passes the command string to the operating system’s default shell and executes it. The output is printed directly to the terminal – it is not captured or returned as a Python value.exit_code: The integer return value ofos.system()is the command’s exit status. A value of0conventionally means the command completed without errors, while any non-zero value signals a failure.- Limitation:
os.system()does not capture the command’s output into a Python variable. For that use case, prefer thesubprocessmodule, specificallysubprocess.run(command, capture_output=True, text=True).
Exercise 16: Walk a Directory Tree
Problem Statement: Write a Python program that recursively lists all files in a directory and its subdirectories, printing the full path of each file found.
Purpose: Traversing an entire directory tree is essential for tasks such as bulk file processing, searching for specific files, calculating total disk usage, and building file indexing tools. os.walk() handles all the recursion automatically, making it far simpler than writing your own recursive function.
Given Input: A sample directory tree created in the script: walk_demo/ with two subdirectories each containing a text file.
Expected Output: Full path of every file found inside the directory tree, one per line.
▼ Hint
os.walk(top)yields a three-element tuple on each iteration:(dirpath, dirnames, filenames).- Use
os.path.join(dirpath, filename)inside the loop to build the full path to each file. - Pass
topdown=Falsetoos.walk()if you need to process deeper directories before their parents.
▼ Solution & Explanation
Explanation:
os.walk("walk_demo"): Returns a generator that traverses the directory tree rooted at the given path. On each step it yields a tuple of: the current directory path, a list of subdirectory names within it, and a list of filenames within it.dirpath, dirnames, filenames: Unpacking the tuple into named variables makes the loop body clear.dirnamescan be modified in-place during iteration to prune branches you want to skip.os.path.join(dirpath, filename): Combines the current directory path with each filename to produce the complete, usable file path. Never concatenate paths with string addition, as it breaks on Windows where the separator is\.
Exercise 17: Join Paths Safely
Problem Statement: Write a Python program that constructs a file path from separate components using os.path.join() and prints the resulting path.
Purpose: Hardcoding path separators like / or \ makes scripts brittle and platform-specific. Using os.path.join() is the correct, portable approach that automatically uses the right separator for the operating system the script runs on.
Given Input: base = "projects", subfolder = "python_exercises", filename = "solution.py"
Expected Output: projects/python_exercises/solution.py (on Unix) or projects\python_exercises\solution.py (on Windows)
▼ Hint
- Pass all path components as separate arguments to
os.path.join()– it accepts any number of arguments. - If any component is an absolute path (starts with
/on Unix or a drive letter on Windows), all previous components are discarded. This is a common source of bugs to be aware of. - Combine
os.path.join()withos.path.abspath()to get the full absolute path from the result.
▼ Solution & Explanation
Explanation:
os.path.join(base, subfolder, filename): Concatenates the path components using the correct OS separator. On Unix the result isprojects/python_exercises/solution.py; on Windows it isprojects\python_exercises\solution.py.- Absolute path override rule: If any argument passed to
os.path.join()is an absolute path, all components before it are dropped. For example,os.path.join("home", "/etc", "config")returns/etc/config, nothome/etc/config. os.path.abspath(full_path): Resolves the joined relative path against the current working directory to produce a complete absolute path. This is useful when you need to pass a definitive path to other functions or display it in logs.
Exercise 18: Get Absolute Path
Problem Statement: Write a Python program that takes a relative file path and converts it to its full absolute path.
Purpose: Relative paths depend on the current working directory, which can change during a script’s execution. Converting to an absolute path early on locks in the location and prevents hard-to-debug errors when functions change directories mid-run or when paths are passed to other modules.
Given Input: relative_path = "data/report.csv"
Expected Output: A full absolute path such as /home/user/projects/data/report.csv (varies by system and working directory)
▼ Hint
- Use
os.path.abspath(path)to resolve a relative path into its full absolute form based on the current working directory. - Use
os.path.dirname(abs_path)to extract just the directory portion of the resolved path. - Use
os.path.basename(abs_path)to extract just the filename from the resolved path.
▼ Solution & Explanation
Explanation:
os.path.abspath(relative_path): Resolves the given relative path by prepending the current working directory. It also normalises any.or..components in the path, so"data/../data/report.csv"becomes a clean absolute path.os.path.dirname(abs_path): Returns everything up to but not including the last path component. For a file path, this gives the containing directory.os.path.basename(abs_path): Returns only the final component of the path – the filename in this case. Together,dirnameandbasenamelet you split any path into its folder and file parts without string manipulation.
Exercise 19: Print Python Version
Problem Statement: Write a Python program that displays the current Python version in two formats: as a human-readable string and as a structured named tuple with individual version components.
Purpose: Knowing the Python version at runtime is essential for writing scripts that conditionally use features only available in certain versions. It is also a standard first line of defence when debugging environment issues across different machines or deployment targets.
Given Input: No input required. The version is provided by the Python interpreter.
Expected Output: Python version: 3.11.4 (main, ...) and Major: 3 Minor: 11 Micro: 4 (values vary by installation)
▼ Hint
- Use
sys.versionto get the full version string including build date and compiler info. - Use
sys.version_infoto access individual components likesys.version_info.major,.minor, and.micro.
▼ Solution & Explanation
Explanation:
sys.version: A plain string containing the full Python version along with build metadata such as the compile date and compiler name. It is useful for display and logging but awkward to parse programmatically.sys.version_info: A named tuple with fieldsmajor,minor,micro,releaselevel, andserial. Accessing individual fields makes version comparisons clean and readable, for example:if sys.version_info.major < 3: raise SystemExit("Python 3 required").- Version guarding: Always use
sys.version_infofor conditional logic rather than parsingsys.versionas a string, since the string format can vary slightly across platforms and builds.
Exercise 20: Read Command-Line Arguments
Problem Statement: Write a Python program that reads arguments passed to it from the command line and prints each argument with its index position.
Purpose: Command-line arguments are the primary way to pass inputs to standalone scripts without hardcoding values or using interactive prompts. This exercise introduces sys.argv, which is the foundation for building CLI tools, utility scripts, and programs that integrate into shell pipelines.
Given Input: Run the script from the terminal as: python solution.py hello world 42
Expected Output: Each argument printed with its index, starting with the script name at index 0.
▼ Hint
sys.argvis a list where index0is always the script filename, and indices1onward are the arguments passed by the user.- Use
enumerate(sys.argv)inside aforloop to iterate with both the index and the value. - All values in
sys.argvare strings. Convert them explicitly if you need a number:int(sys.argv[1]).
▼ Solution & Explanation
Explanation:
sys.argv: A list of strings populated by the Python interpreter before the script runs. The first element (sys.argv[0]) is always the script name or path, making the actual user-supplied arguments start at index1.len(sys.argv): Gives the total count of all arguments including the script name. Checking this before accessingsys.argv[1]prevents anIndexErrorwhen the user runs the script without providing any arguments.enumerate(sys.argv): Yields each argument paired with its position index, removing the need for a manual counter variable and making the output self-documenting.
Exercise 21: Exit a Program
Problem Statement: Write a Python program that checks whether a required command-line argument is provided and exits gracefully with a descriptive error message if it is missing.
Purpose: Controlled program termination is a sign of well-written scripts. Rather than letting a program crash with a cryptic traceback, sys.exit() lets you stop execution cleanly, communicate the reason to the user, and signal success or failure to the calling shell or process manager.
Given Input: Run without arguments (python solution.py) to trigger the exit, or with one argument (python solution.py Alice) to proceed normally.
Expected Output: Error: Please provide a name as an argument. followed by exit, or Hello, Alice! if the argument is present.
▼ Hint
- Check
len(sys.argv) < 2to detect a missing argument, sincesys.argv[0]is always the script name. - Call
sys.exit("Error message")to print a message to stderr and terminate with exit code1. - Pass an integer to
sys.exit()to set a specific exit code:sys.exit(0)for success,sys.exit(1)for general errors.
▼ Solution & Explanation
Explanation:
len(sys.argv) < 2: Sincesys.argv[0]is always the script name, a length less than2means no user-supplied arguments were given. This guard must come before any attempt to accesssys.argv[1]to avoid anIndexError.sys.exit("Error: ..."): When called with a string argument, Python prints that string tostderrand exits the process with code1. This signals failure to the calling shell, which is important for scripts used in automated pipelines.- Exit codes matter: A shell script or CI pipeline checks the exit code of each command. Using
sys.exit(0)for success andsys.exit(1)(or a non-zero value) for failure makes your script a well-behaved participant in larger automated workflows.
Exercise 22: Get Platform Info
Problem Statement: Write a Python program that identifies the current operating system platform and prints a human-readable description of it.
Purpose: Writing cross-platform scripts requires knowing which OS the code is running on so that platform-specific behaviour – such as choosing the right shell command, file separator, or config path – can be handled correctly. This exercise introduces the two most common ways to detect the platform at runtime.
Given Input: No input required. The platform is detected from the runtime environment.
Expected Output: Platform: linux and Detailed platform: Linux-5.15.0-x86_64 (values vary by system)
▼ Hint
- Use
sys.platformfor a short identifier:"linux","darwin"(macOS), or"win32"(Windows). - Use
platform.platform()from the built-inplatformmodule for a more detailed description including OS version and architecture. - Use
platform.system()to get just the OS name as a clean string:"Linux","Darwin", or"Windows".
▼ Solution & Explanation
Explanation:
sys.platform: A short lowercase string set by the Python interpreter at startup. The most common values are"linux"for Linux,"darwin"for macOS, and"win32"for all versions of Windows including 64-bit. It is the simplest way to branch platform-specific logic.platform.system(): Returns a cleaner, title-cased OS name such as"Linux","Darwin", or"Windows"without the extra build detail. It is easier to read in output intended for end users.platform.platform(): Returns a full descriptive string that includes the OS name, version, and hardware architecture. It is most useful in diagnostic logs and bug reports where full environment detail is needed.platform.machine(): Returns the hardware architecture identifier such as"x86_64"or"arm64", which is useful when building or distributing architecture-specific packages.
Exercise 23: Inspect sys.path
Problem Statement: Write a Python program that prints all the directories Python searches when looking for modules to import, displaying each directory on a separate line.
Purpose: Understanding sys.path is essential for diagnosing ModuleNotFoundError problems, understanding how Python resolves imports, and knowing where to place custom modules so they can be imported without any configuration. This exercise builds a mental model of how Python’s import system works.
Given Input: No input required. The path list is maintained by the Python interpreter.
Expected Output: A numbered list of all directories in the module search path (output varies by system and virtual environment).
▼ Hint
sys.pathis a regular Python list of strings, so you can iterate over it with aforloop or useenumerate()to add index numbers.- The first entry (
sys.path[0]) is typically an empty string""or the script’s own directory, meaning Python checks the current directory first. - You can also print the length with
len(sys.path)to see how many locations are being searched.
▼ Solution & Explanation
Explanation:
sys.path: A list of directory strings that Python scans in order when animportstatement is encountered. The first matching module found wins. This list is assembled from the script’s directory, thePYTHONPATHenvironment variable, and installation-specific defaults.- Empty string entry: An empty string
""at any position insys.pathrepresents the current working directory. The conditionalpath if path else '(current directory)'makes this explicit in the output rather than printing a blank line. - Order matters: Python imports the first module it finds as it walks the list from index 0 onward. If two directories both contain a module with the same name, the one in the lower-indexed directory takes precedence – a common source of shadowing bugs.
Exercise 24: Add to sys.path
Problem Statement: Write a Python program that dynamically adds a custom directory to sys.path so that modules stored in that directory can be imported without installing them as packages.
Purpose: There are situations where you need to import a module from a non-standard location – for example, a shared utilities folder, a sibling project directory, or a path determined at runtime. Modifying sys.path programmatically is the direct way to achieve this without changing environment variables or restructuring the project.
Given Input: A custom directory path custom_modules containing a simple Python file greet.py (both created in the script).
Expected Output: Hello from custom module!
▼ Hint
- Use
sys.path.insert(0, directory_path)to add your directory at the front of the search list so it is checked before any other location. - Use
os.path.abspath()when constructing the path to insert, to avoid issues with relative paths changing meaning if the working directory changes later. - Check that the path is not already in
sys.pathbefore inserting to avoid duplicates:if directory_path not in sys.path.
▼ Solution & Explanation
Explanation:
sys.path.insert(0, custom_dir): Inserts the custom directory at position 0 so it is the first location Python checks during any subsequent import. Usingappend()instead would add it to the end, meaning it would only be consulted after all standard library and site-packages locations.os.path.abspath(custom_dir): Converts the relative directory name into a full absolute path. This ensures the entry insys.pathremains valid even if the working directory changes later in the same script.- Duplicate check: The
if custom_dir not in sys.pathguard prevents the same directory from being added multiple times if the script or function is called more than once, keepingsys.pathclean.
Exercise 25: Get Recursion Limit
Problem Statement: Write a Python program that retrieves and prints the maximum recursion depth allowed by the current Python interpreter.
Purpose: Python limits how deeply functions can call themselves to prevent a stack overflow from consuming all available memory. Knowing this limit helps you understand why deeply recursive algorithms fail with a RecursionError and prepares you for the next exercise where the limit is adjusted.
Given Input: No input required.
Expected Output: Current recursion limit: 1000 (the default on most Python installations)
▼ Hint
- Use
sys.getrecursionlimit()to retrieve the current maximum recursion depth as an integer. - Write a simple recursive function that counts down from a number to demonstrate what happens as the call stack grows toward the limit.
▼ Solution & Explanation
Explanation:
sys.getrecursionlimit(): Returns the current maximum depth of the Python interpreter call stack as an integer. The default value on most systems is1000, meaning a chain of more than 1000 nested function calls will raise aRecursionError.- What counts as a level: Every function call – including calls made indirectly through other functions – increments the call stack depth by one. A recursive function that calls itself 1001 times will exceed the default limit on the 1001st call.
- Practical context: Many real-world recursive algorithms such as tree traversal, parsing nested structures, or depth-first search can easily exceed 1000 levels on large inputs. In those cases the limit must either be raised or the algorithm rewritten iteratively.
Exercise 26: Change Recursion Limit
Problem Statement: Write a Python program that increases the recursion limit and then tests it by running a recursive function that would fail under the default limit.
Purpose: Some legitimate algorithms – such as processing deeply nested JSON, traversing large trees, or implementing certain parsers – require a deeper call stack than Python’s default allows. This exercise shows how to raise the limit safely and why it should be done with care.
Given Input: No input required. The recursion depth is set within the script.
Expected Output: Old limit: 1000, New limit: 2000, and Recursion test with depth 1500: passed
▼ Hint
- Use
sys.setrecursionlimit(n)to set a new maximum recursion depth before calling the recursive function. - Save the original limit with
sys.getrecursionlimit()before changing it so you can restore it afterward if needed. - Be cautious: setting the limit too high can cause a genuine stack overflow and crash the Python interpreter rather than raising a catchable
RecursionError.
▼ Solution & Explanation
Explanation:
sys.setrecursionlimit(2000): Raises the maximum allowed call stack depth to 2000, allowing the subsequent recursive call with depth 1500 to complete without raising aRecursionError. The new limit takes effect immediately for all subsequent calls in the process.- Restoring the original limit: Saving and restoring the old limit via
sys.setrecursionlimit(old_limit)is good practice, especially in libraries or test suites where side effects on global interpreter state should be minimised. - Safety ceiling: Setting the limit to an extremely large value such as
10**6can cause a hard crash (segmentation fault) because the OS-level thread stack is exhausted before Python can raise a cleanRecursionError. Stay within a few thousand unless you have a specific, tested need for more.
Exercise 27: Script Info Logger
Problem Statement: Write a Python program that collects information about itself – its filename, the current working directory, and the OS platform – and writes all of it to a log file called script_info.log.
Purpose: Logging runtime context is a fundamental practice in production scripts and scheduled jobs. When something goes wrong, a log that captures where the script ran, on what platform, and under which filename gives you the starting point for diagnosis. This exercise combines sys and os together for the first time in a practical output task.
Given Input: No input required. All values are derived from the runtime environment.
Expected Output: A file script_info.log created in the current directory, and the log contents printed to the terminal.
▼ Hint
- Use
sys.argv[0]to get the script filename,os.getcwd()for the current directory, andsys.platformfor the OS identifier. - Open the log file with
open("script_info.log", "w")and write each piece of information on a new line. - Use
sys.stdout.write()as an alternative toprint()to write directly to standard output, reinforcing awareness of the underlying stream.
▼ Solution & Explanation
Explanation:
sys.argv[0]: Always holds the name or path of the script itself as provided to the interpreter. In an interactive session this is an empty string or a special identifier, but when running a saved script it reflects the actual filename.sys.version.split()[0]: Extracts just the version number (e.g.3.11.4) from the full version string, discarding the build date and compiler detail that follow it.sys.stdout.write(line + "\n"): Writes directly to standard output without the automatic newline and space-separated argument behaviour ofprint(). It makes the parallel between writing to the file and writing to the terminal explicit, highlighting that both are just file-like streams.
Exercise 28: Directory Size Calculator
Problem Statement: Write a Python program that calculates the total size of all files in a directory tree and displays the result in bytes, kilobytes, and megabytes.
Purpose: Calculating disk usage is a practical task in backup tools, storage monitoring scripts, and deployment pipelines. This exercise combines os.walk() for recursion with os.path.getsize() for per-file measurement, reinforcing how the two functions work together.
Given Input: A sample directory tree size_demo/ created in the script with a few files of varying sizes.
Expected Output: Total size printed in bytes, KB, and MB (exact values depend on the test files created).
▼ Hint
- Use
os.walk(directory)to traverse all subdirectories andos.path.getsize()on each file to accumulate the total. - Build the full file path inside the loop with
os.path.join(dirpath, filename)before passing it togetsize(). - Divide the total byte count by
1024for KB and by1024 ** 2for MB, then format with two decimal places using:.2f.
▼ Solution & Explanation
Explanation:
total_bytes += os.path.getsize(full_path): Accumulates the size of every file encountered during the walk into a running total.getsize()reads directly from filesystem metadata, so there is no need to open or read any file content.os.path.join(dirpath, filename): Constructs the correct full path to each file within the loop. Passing justfilenametogetsize()would fail unless the file happened to be in the current working directory.- Unit conversion: Dividing by
1024converts bytes to kibibytes (KB) and by1024 ** 2converts to mebibytes (MB). The:.2fformat specifier rounds the float to two decimal places for a clean display.
Exercise 29: Environment Config Loader
Problem Statement: Write a Python program that simulates loading application configuration by reading multiple environment variables with fallback defaults, then prints a formatted summary of the configuration to standard output.
Purpose: Reading configuration from environment variables is the industry-standard approach for twelve-factor applications. It keeps secrets and environment-specific settings out of source code. This exercise combines os.environ.get() with sys.stdout to build a realistic config-loading pattern used in web apps, APIs, and CLI tools.
Given Input: Environment variables APP_HOST, APP_PORT, and APP_DEBUG – set within the script to simulate a configured environment.
Expected Output: A formatted configuration summary printed to stdout showing each key and its resolved value.
▼ Hint
- Use
os.environ.get("KEY", "default_value")for each setting so the script works even when variables are not set in the environment. - Store all config key-value pairs in a dictionary and iterate over it to print the summary, keeping the loading and display logic separate.
- Use
sys.stdout.write()instead ofprint()for at least part of the output to practise writing to the standard output stream directly.
▼ Solution & Explanation
Explanation:
os.environ.get("KEY", "default"): Reads the environment variable namedKEYand returns its string value if present, or the second argument as a fallback if it is not set. This pattern ensures the application always has a usable value for every setting regardless of the deployment environment.- Dictionary-based config: Storing all settings in a single
configdict separates the loading step from the display and usage steps. This mirrors how configuration libraries such asdynaconfandpython-decouplework internally. sys.stdout.write(): Writes a string directly to the standard output stream. Unlikeprint(), it does not add a trailing newline automatically, giving you full control over line endings. Thef"{key:<12}"format left-aligns the key in a field of 12 characters, producing a neatly aligned two-column layout.
Exercise 30: Recursive File Finder
Problem Statement: Write a Python program that accepts a file extension as a command-line argument and recursively searches the current directory tree for all files matching that extension, printing the full path of each match.
Purpose: This capstone exercise combines everything covered in the module: sys.argv for input, sys.exit() for validation, os.walk() for traversal, os.path.join() for path construction, and os.path.splitext() for extension matching. It mirrors a real-world utility script that you might use or build as part of a larger automation pipeline.
Given Input: Run as python solution.py .txt from the terminal. A sample directory tree with mixed file types is created by the script for testing.
Expected Output: Full paths of all .txt files found in the directory tree, followed by a count of matches.
▼ Hint
- Use
sys.exit()early iflen(sys.argv) < 2to inform the user how to provide the extension argument. - Normalise the extension with
.lower()and ensure it starts with a dot so bothtxtand.txtare accepted as valid input. - Inside the
os.walk()loop, useos.path.splitext(filename)[1].lower()to extract and compare each file’s extension.
▼ Solution & Explanation
Explanation:
sys.argvvalidation and normalisation: Checkinglen(sys.argv) < 2before accessingsys.argv[1]prevents anIndexError. The dot-prefix check and.lower()call make the tool forgiving so users can pass eithertxtor.TXTand get the same result.os.path.splitext(filename)[1].lower(): Extracts the extension from each filename and normalises its case before comparing. This prevents a mismatch between.TXTin the filename and.txtin the search term on case-sensitive filesystems.- Collecting into a list before printing: Appending matches to a list rather than printing inside the loop separates the search logic from the display logic. This makes it easy to extend the script later – for example, to sort the results, filter by size, or pass the list to another function.

Leave a Reply