Your country

Tools that support it use your country for local currency, number formats, units and paper size. Your choice is saved only in this browser.

Type a name or a two-letter code. Use the up and down arrow keys to move through the countries, Enter to choose one and Escape to close.

Python  Module 16 – Practical Python: text, CLIs, web, automation and security

Working with the OS: os, sys, shutil, platform

Read environment variables, open files relative to the script, stop with an exit status, find programs and identify the system with os, sys and platform.

  • Intermediate
  • 20 minutes
  • Examples run with Python 3.14.8 and Pyodide 314.0.7
  • By MySmartCoPilot
Free core, Pro depth: 8 of 20 minutes free
Free: A process starts with arguments, an environment and a folder · sys, platform and os say what the script runs on · Environment variables arrive as strings · 3 more sections. With a pass: 2 in-depth parts and 3 interview answers, about 12 minutes.

What you will learn

  • Inspect the interpreter, the operating system and the process with sys, platform and os
  • Read settings from environment variables with defaults, and open files relative to the script
  • Report success or failure to the caller with sys.exit() and an exit status
  • Write path and newline handling that behaves the same on Windows, macOS and Linux
  • Predict what a parent process sees when its child changes the environment or exits, and check disk space first

Before you start

What you’ll learn · Before you start

What you will learn

  • Inspect the interpreter, the operating system and the process with sys, platform and os
  • Read settings from environment variables with defaults, and open files relative to the script
  • Report success or failure to the caller with sys.exit() and an exit status
  • Write path and newline handling that behaves the same on Windows, macOS and Linux
  • Predict what a parent process sees when its child changes the environment or exits, and check disk space first

Before you start

On this page

A report script works in your terminal and fails every night under the scheduler: the setting it needs is not set there, prices.csv is not in the folder it starts in, and the job still reports success, because it exits with status 0 whatever happened. Each of those failures is about how a process meets the computer it runs on.

Four standard modules handle that meeting. os describes and changes the process: its environment variables in os.environ, its working directory and the CPUs it may use. sys describes the interpreter: the arguments in sys.argv, the platform in sys.platform, the version in sys.version_info, and sys.exit() to stop with an exit status. shutil copies, moves and deletes whole files and folders, and finds programs with shutil.which(). platform names the operating system and processor in words a person reads.

A process starts with arguments, an environment and a folder

Every program, a Python script included, is started by another one: a shell, a scheduler or a test runner. The parent passes three things, the arguments, a copy of its environment variables and its working directory, and the child hands back one number when it ends, its exit status: The small number a program hands back to whatever started it: 0 for success, anything else for failure. Shells, CI jobs and schedulers read it; by convention 2 means a wrong command line and 1 any other error. More in “Designing error handling for real programs”:

Flow: a parent starts Python with arguments, an environment copy and a working directory; the process ends with an exit status.The parent: a shell, a scheduleror another programStarting python3 report.py --month 3,it hands over three thingsYour Python processsys.exit(n) ends the process:the parent reads exit status nthe program and its argumentsa copy of its environment variablesits working directorysys.argv: report.py, --month, 3os.environ: a copy read at start-upos.getcwd(): where relative paths startchanges the child makes stay in the child

What a Python process gets when it starts, and what it hands back

Text description of the diagram

1. A parent program, such as a shell or a scheduler, starts python3 report.py --month 3. 2. It hands the new process three things: the program and its arguments, a copy of its own environment variables, and its own working directory. 3. Inside Python they appear as sys.argv (the script name and its arguments), os.environ (a copy of the environment, read when the os module is first imported) and os.getcwd() (the folder that relative paths start from). Changes the process makes to them stay in the process and in the processes it starts; the parent never sees them. 4. sys.exit(n) ends the process, and the parent reads n as its exit status: 0 means success.

Each of the three is the child’s own copy, so a script can change them freely and the parent never sees the change. Step through one run of a report script and watch which changes stay inside it:

Interactive · message by message A shell starts report.py, and what comes back Step through one run of a script. Watch which changes stay inside the script and which number goes back to the shell.
A shell starts report.py, and what comes back, step 8 of 8. Messages so far: the shell to report.py: report.py --month 3; report.py to a program it starts: start: a copy of env; a program it starts to report.py: exit status 0; report.py to the shell: exit status 0.the shell$? is 0, SHOP_MODE=stagingreport.pycwd: /home/asha/reportsa program it startsfinishedreport.py --month 3start: a copy of envexit status 0exit status 0

The drawing shows the whole scene; its 8 steps are listed below.

Every step as text
  1. The shell starts Python. In the folder /home/asha, a shell runs python3 report.py --month 3. The shell's own environment holds SHOP_MODE=staging.
  2. A copy of the environment. The new process receives a copy of the shell's environment variables, so os.environ['SHOP_MODE'] is 'staging' inside the script too.
  3. And the working folder. It also starts in the shell's working directory, /home/asha. A relative name such as prices.csv is looked up there, wherever the script itself is stored.
  4. The script changes its copy. report.py assigns os.environ['SHOP_MODE'] = 'test'. Only its own copy changes; the shell still holds staging.
  5. Its child gets the change. The script starts another program with subprocess. That program receives a copy of the script's environment as it is now, so it sees 'test'.
  6. The child reports back. The child finishes and hands back one number, its exit status, 0 for success, which subprocess.run() returns in returncode.
  7. The script moves folder. os.chdir('reports') moves the script to /home/asha/reports. The shell's working directory does not move.
  8. The script exits. report.py ends with sys.exit(0). The shell receives that number, 0, which it shows in $?, and its environment and folder are as they were.

Only the exit status travelled back. The four modules divide the work like this:

Module The question it answers Calls you use most
os What is this process’s environment and working directory? os.environ, os.getcwd(), os.getpid(), os.process_cpu_count()
sys Which interpreter runs, with which arguments, and how does it stop? sys.argv, sys.exit(), sys.platform, sys.version_info
shutil How do I copy, move or delete whole trees, and where is a program? shutil.copy2(), shutil.move(), shutil.rmtree(), shutil.which()
platform Which operating system and processor, in words? platform.system(), platform.machine(), platform.python_version()

Checkpoint

Check: What a process gets and hands back

  1. Question 1 of 2 The shell has SHOP_MODE=staging. It starts report.py, which runs os.environ["SHOP_MODE"] = "test" and exits. What does the shell's echo $SHOP_MODE print afterwards?

    Choose one answer.

    Show the answer: Question 1 of 2

    Answer: staging

    A process gets a copy of its parent's environment when it starts. Assigning to os.environ changes that copy and the copies of the programs the script starts later, never the shell's own variables.

  2. Question 2 of 2 After that assignment, report.py starts another program with subprocess.run(). Which value of SHOP_MODE does that program see?

    Choose one answer.

    Show the answer: Question 2 of 2

    Answer: test

    Each process copies its environment from the one that starts it. The shell's copy still says staging, the script's says test, and the program the script starts inherits test.

sys, platform and os say what the script runs on

The interpreter, the operating system and the CPUs Python · system_report.py
"""A short report on the interpreter, the operating system and the process running this script."""
import os
import platform
import sys

print("Python", platform.python_version(), platform.python_implementation())
print("sys.version_info >= (3, 14):", sys.version_info >= (3, 14))
print("sys.platform:", sys.platform)
print("platform.system():", platform.system())
print("platform.machine():", platform.machine())
print("os.name:", os.name)
print("CPUs this process may use:", os.process_cpu_count())
print("arguments after the script name:", sys.argv[1:])

Output

Python 3.14.8 CPython
sys.version_info >= (3, 14): True
sys.platform: darwin
platform.system(): Darwin
platform.machine(): arm64
os.name: posix
CPUs this process may use: 18
arguments after the script name: []

This output changes from run to run: the platform, the processor and the number of CPUs depend on the computer that runs it

Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 system_report.py

Version note

In the browser, Python runs on WebAssembly, so the same program reports emscripten and wasm32 there, and a single CPU.

In your browser, Pyodide 314.0.7 (CPython 3.14.2) prints:

Python 3.14.2 CPython
sys.version_info >= (3, 14): True
sys.platform: emscripten
platform.system(): Emscripten
platform.machine(): wasm32
os.name: posix
CPUs this process may use: 1
arguments after the script name: []

Compare sys.version_info with a tuple, sys.version_info >= (3, 14), never the sys.version string. Code that branches on the system should test sys.platform: "win32" on Windows, "darwin" on macOS, "linux" on Linux and "emscripten" in the browser. platform.system() says the same in words for reports and logs. os.process_cpu_count() counts the CPUs this process may use, which can be fewer than os.cpu_count() reports for the whole machine. sys.argv[0] is the script’s own name and the arguments follow it, which is why the report prints sys.argv[1:]. sys.executable is the interpreter running the script: start helper scripts with it, so that they run on the same Python and in the same virtual environment.

Checkpoint

Check: sys, platform and os on the running system

  1. Question 1 of 2 Why is sys.version_info >= (3, 14) the right version check, rather than comparing the sys.version string with "3.14"?

    Choose one answer.

    Show the answer: Question 1 of 2

    Answer: Tuples compare number by number, while strings compare character by character, so "3.9" sorts after "3.14"

    sys.version_info is a tuple of numbers, so (3, 9) < (3, 14) as it should be. The string "3.9" is greater than "3.14", which makes string checks pass on the wrong versions.

  2. Question 2 of 2 A script needs one code path for Windows and another for every other system. Which test is meant for that decision?

    Choose one answer.

    Show the answer: Question 2 of 2

    Answer: sys.platform == "win32"

    sys.platform is the identifier for code decisions: "win32" on Windows, "darwin" on macOS, "linux" on Linux and "emscripten" in the browser. platform.system() says the same in words for logs.

Environment variables arrive as strings

Settings that change from one computer to another, such as a mode, a number of workers or an API token, usually come from environment variable: A name with a text value that a process receives from the program that started it, such as APP_PORT=9000. Python reads them from os.environ, always as str, and every process it starts gets a copy of them. More in “Config files, environment variables and secrets”. This program sets two of them the way a shell would, then reads four settings. Step through it, or press Edit and run it with other values:

Interactive · line by line Settings read from os.environ, step by step The program sets two variables the way a shell would, then reads four settings. Watch what type each value has when it arrives.

Program · settings_from_env.py

"""Settings from environment variables."""
import os

os.environ["SHOP_MODE"] = "staging"
os.environ["SHOP_WORKERS"] = "8"

mode = os.environ.get("SHOP_MODE", "production")
workers = int(os.environ.get("SHOP_WORKERS", "4"))
flag = os.environ.get("SHOP_DEBUG", "")
debug = flag.lower() in {"1", "true", "yes"}
print(f"mode={mode!r} workers={workers} debug={debug}")

try:
    token = os.environ["SHOP_API_TOKEN"]
except KeyError as missing:
    print("not set:", missing)

print("SHOP_DEBUG" in os.environ, os.getenv("SHOP_DEBUG"))
del os.environ["SHOP_MODE"]
print(os.environ.get("SHOP_MODE", "production"))

Variables

After line 20: mode is 'staging'; workers is 8; flag is ''; debug is False.mode'staging'workers8flag''debugFalse
  • changed in this step

Printed so far

mode='staging' workers=8 debug=False
not set: 'SHOP_API_TOKEN'
False None
production

Every step was recorded from a run with Python 3.14.8 on macOS 26 arm64.

The drawing shows the variables when the program ends, and the program's 17 steps are listed below.

Line run 20
Next line end
Every step as text
  1. Start. No line has run yet, so there are no variables. Python starts with line 1.
  2. Line 1. """Settings from environment variables.""" runs.
  3. Line 2. import os loads os.
  4. Line 4. os.environ["SHOP_MODE"] = "staging" runs.
  5. Line 5. os.environ["SHOP_WORKERS"] = "8" runs. Both values are stored as strings, as every environment variable is. A shell that ran export SHOP_WORKERS=8 would have stored the same text.
  6. Line 7. mode = os.environ.get("SHOP_MODE", "production") sets mode to 'staging'. Key point .get() returns the value when the variable is set, and the default only when it is missing, so mode is 'staging'.
  7. Line 8. workers = int(os.environ.get("SHOP_WORKERS", "4")) sets workers to 8. int() turns the text '8' into the number 8. Without it, workers would be a string, and workers + 1 would raise TypeError.
  8. Line 9. flag = os.environ.get("SHOP_DEBUG", "") sets flag to ''.
  9. Line 10. debug = flag.lower() in {"1", "true", "yes"} sets debug to False. SHOP_DEBUG is not set, so flag holds the default, an empty string. Only the listed spellings count as true, so debug is False.
  10. Line 11. print(f"mode={mode!r} workers={workers} debug={debug}") prints mode='staging' workers=8 debug=False.
  11. Line 13. try: runs.
  12. Line 14. token = os.environ["SHOP_API_TOKEN"] runs. Key point Square brackets raise KeyError for a missing variable, which is the right behaviour for a setting such as an API token that must exist.
  13. Line 15. Line 15 runs.
  14. Line 16. print("not set:", missing) prints not set: 'SHOP_API_TOKEN'. missing no longer exists.
  15. Line 18. print("SHOP_DEBUG" in os.environ, os.getenv("SHOP_DEBUG")) prints False None.
  16. Line 19. del os.environ["SHOP_MODE"] runs. del unsets SHOP_MODE for this process and for the programs it starts. The shell that started the script keeps its own copy.
  17. Line 20. print(os.environ.get("SHOP_MODE", "production")) prints production. That was the last line, so the program ends. Every setting arrived as text, and every missing one as a default, None or a KeyError. Nothing outside this process changed.

os.environ behaves like a dictionary of strings. .get(name, default) gives a default when the variable is not set, while os.environ[name] raises KeyError, the right choice for a setting that must exist. Every value is text, so numbers and flags need converting. Changes made through os.environ reach this process and the programs it starts, never the shell that started it. Secrets such as API tokens belong there too, out of the code and off the command line, which other users of a computer can often read; every program your script starts receives them.

Checkpoint

Check: Settings from environment variables

  1. Question 1 of 2 SHOP_API_TOKEN is not set. What does os.environ["SHOP_API_TOKEN"] do?

    Choose one answer.

    Show the answer: Question 1 of 2

    Answer: It raises KeyError

    os.environ behaves like a dictionary, so a missing key raises KeyError, which suits a setting that must exist. os.environ.get() and os.getenv() return None, or the default you pass, instead.

  2. Question 2 of 2 SHOP_WORKERS=8 is set. What does os.environ.get("SHOP_WORKERS", 4) + 1 do?

    Choose one answer.

    Show the answer: Question 2 of 2

    Answer: It raises TypeError, because the value is the string '8'

    Environment variables are always strings. Convert with int(os.environ.get("SHOP_WORKERS", "4")), and give the default as a string too, so that both paths go through the same conversion.

Relative paths start in the working directory, not beside the script

The same open() before and after a change of directory Python · cwd_trap.py
"""A file opened by a relative name is looked up in the working directory, not next to the script."""
import os
from pathlib import Path

HERE = Path(__file__).resolve().parent           # the folder this script lives in
(HERE / "prices.csv").write_text("item,paise\ntea,1500\n", encoding="utf-8")
(HERE / "reports").mkdir(exist_ok=True)

def read_relative():
    with open("prices.csv", encoding="utf-8") as f:          # relative to os.getcwd()
        return f.readline().strip()

def read_beside_script():
    return (HERE / "prices.csv").read_text(encoding="utf-8").splitlines()[0]

print("working directory is the script's folder:", Path.cwd() == HERE)
print("relative name:", read_relative())

os.chdir(HERE / "reports")                       # what a scheduler, an IDE or a cd before the command does
print("working directory is the script's folder:", Path.cwd() == HERE)
try:
    print("relative name:", read_relative())
except FileNotFoundError as e:
    print("relative name: FileNotFoundError:", e.strerror)
print("next to the script:", read_beside_script())

Output

working directory is the script's folder: True
relative name: item,paise
working directory is the script's folder: False
relative name: FileNotFoundError: No such file or directory
next to the script: item,paise

Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 cwd_trap.py

A relative name such as "prices.csv" is looked up in the working directory, which is wherever the caller happened to be. A scheduler, an editor’s Run button or a cd before the command can each change it, and the script breaks. Path(__file__).resolve().parent is the script’s own folder, so build paths to your own files from it.

The same paths feed shutil. shutil.copy2() copies a file with its timestamps, shutil.copytree() copies a whole folder and shutil.move() moves a file or folder, even to another disk. shutil.rmtree() deletes a folder and everything in it, with no undo and no recycle bin, so check the path it receives before calling it.

Checkpoint

Check: Relative paths and the working directory

  1. Question 1 of 2 A script stored in /opt/shop opens "prices.csv" by its relative name. The scheduler starts it with the working directory /root. Which file does open() look for?

    Choose one answer.

    Show the answer: Question 1 of 2

    Answer: /root/prices.csv

    open("prices.csv") means "prices.csv in the current working directory". Build the path from Path(__file__).resolve().parent to read the file beside the script.

  2. Question 2 of 2 Which expression gives the folder the script itself is stored in, whatever the working directory is?

    Choose one answer.

    Show the answer: Question 2 of 2

    Answer: Path(__file__).resolve().parent

    Path(__file__).resolve().parent does not depend on the working directory, so files built from it are found from a scheduler, an editor's Run button or any terminal.

sys.exit() ends the script with a status the caller reads

A version check that stops the program Python · require_python.py
"""sys.exit() with a message: the message goes to standard error and the exit status is 1."""
import sys


def require_python(minimum):
    if sys.version_info < minimum:
        wanted = ".".join(str(n) for n in minimum)
        running = f"{sys.version_info.major}.{sys.version_info.minor}"
        sys.exit(f"This tool needs Python {wanted} or newer; this is Python {running}.")


try:
    require_python((3, 10))
    print("Python 3.10 or newer: carry on")
    require_python((3, 15))
    print("this line is never reached")
finally:
    print("the finally block still ran: sys.exit() raises SystemExit")

Output (exit status 1)

Python 3.10 or newer: carry on
the finally block still ran: sys.exit() raises SystemExit

Printed as an error (standard error)

This tool needs Python 3.15 or newer; this is Python 3.14.

Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 require_python.py

sys.exit() raises SystemExit, so finally blocks and with statements still clean up, as the line from the finally block shows. An integer becomes the exit status: 0 means success, any other number failure, and 2 conventionally a mistake on the command line, which is what argparse uses. A string is printed on standard error and gives status 1, which shells, CI jobs and schedulers read as failure. That is how the nightly job of the opening should end when its setting is missing: with a message that names the setting and a status that makes the scheduler report a failure, instead of a status of 0 and an empty report.

Checkpoint

Check: sys.exit() and the exit status

  1. Question 1 of 2 A script ends with sys.exit("setting SHOP_API_TOKEN is missing"). Which exit status does the scheduler see?

    Type a number.

    Show the answer: Question 1 of 2

    Answer: 1 exit status

    When sys.exit() gets a string, Python prints it on standard error and exits with status 1, which the scheduler reads as a failure.

  2. Question 2 of 2 sys.exit(2) runs inside a try: whose finally: closes a log file. What happens?

    Choose one answer.

    Show the answer: Question 2 of 2

    Answer: The finally block closes the file, then the program ends with status 2

    sys.exit() raises SystemExit, so clean-up code still runs, and the integer it carries becomes the exit status: 2 here, the usual status for a command-line mistake.

Check yourself

Each question below checks one of the five ideas about processes, and the session starts with the idea you know least well.

Practice that adapts to you

Practise this lesson

10 questions about 11 ideas of this lesson. Each answer is explained at once, and what you get right is kept in this browser.

  1. Question 1 of 10 Which of these does a new process receive from the program that starts it?

    Choose every answer that is right.

    Show the answer: Question 1 of 10

    Answer:

    • Its arguments
    • A copy of the environment variables
    • Its working directory

    A parent passes the arguments, a copy of its environment and its working directory; the child hands back one number, its exit status, when it ends.

  2. Question 2 of 10 You export SHOP_API_TOKEN in your shell's start-up file. The script works in your terminal and raises KeyError when the scheduler runs it. What explains it?

    Choose one answer.

    Show the answer: Question 2 of 10

    Answer: The scheduler is not your shell, so it starts the script with its own environment, without your exports

    The environment comes from the parent. Give the job its settings where the scheduler can pass them, and stop with a clear message when a required one is missing.

  3. Question 3 of 10 Which test tells reliably whether the interpreter is Python 3.10 or newer?

    Choose one answer.

    Show the answer: Question 3 of 10

    Answer: sys.version_info >= (3, 10)

    Compare sys.version_info with a tuple; every other form compares text or only part of the version.

  4. Question 4 of 10 A process is pinned to 2 of a machine's 16 CPUs. Which call gives the number to size its process pool by?

    Choose one answer.

    Show the answer: Question 4 of 10

    Answer: os.process_cpu_count()

    os.process_cpu_count() can be smaller than os.cpu_count(), and it is the one that says how many CPUs the process can really keep busy.

  5. Question 5 of 10 What does os.getenv("SHOP_DEBUG") return when SHOP_DEBUG is not set?

    Choose one answer.

    Show the answer: Question 5 of 10

    Answer: None

    os.getenv(name) and os.environ.get(name) return None for a missing variable; pass a default as the second argument to get something else.

  6. Question 6 of 10 SHOP_DEBUG=0 is set to turn debugging off. What does debug = bool(os.environ.get("SHOP_DEBUG")) give?

    Choose one answer.

    Show the answer: Question 6 of 10

    Answer: True, because "0" is a non-empty string

    Environment values are text, so turn a flag into True or False on purpose, as the lesson's program does with flag.lower() in {"1", "true", "yes"}.

  7. Question 7 of 10 What does cwd_trap.py print?

    What does this program print? Choose one answer.

    """A file opened by a relative name is looked up in the working directory, not next to the script."""
    import os
    from pathlib import Path
    
    HERE = Path(__file__).resolve().parent           # the folder this script lives in
    (HERE / "prices.csv").write_text("item,paise\ntea,1500\n", encoding="utf-8")
    (HERE / "reports").mkdir(exist_ok=True)
    
    def read_relative():
        with open("prices.csv", encoding="utf-8") as f:          # relative to os.getcwd()
            return f.readline().strip()
    
    def read_beside_script():
        return (HERE / "prices.csv").read_text(encoding="utf-8").splitlines()[0]
    
    print("working directory is the script's folder:", Path.cwd() == HERE)
    print("relative name:", read_relative())
    
    os.chdir(HERE / "reports")                       # what a scheduler, an IDE or a cd before the command does
    print("working directory is the script's folder:", Path.cwd() == HERE)
    try:
        print("relative name:", read_relative())
    except FileNotFoundError as e:
        print("relative name: FileNotFoundError:", e.strerror)
    print("next to the script:", read_beside_script())
    Show the answer: Question 7 of 10

    Answer: it prints

    working directory is the script's folder: True
    relative name: item,paise
    working directory is the script's folder: False
    relative name: FileNotFoundError: No such file or directory
    next to the script: item,paise

    After os.chdir(), the relative name "prices.csv" is looked up in the reports folder, where no such file exists. The path built from Path(__file__).resolve().parent does not depend on the working directory, so it still finds the file.

  8. Question 8 of 10 A clean-up script calls shutil.rmtree(path) with a folder name read from a configuration file. Which check belongs before the call?

    Choose one answer.

    Show the answer: Question 8 of 10

    Answer: Resolve the path and confirm that it is inside the folder the script owns

    shutil.rmtree() deletes a folder and everything in it, with no undo. Resolve the path and check that it is inside the folder the script is meant to clean, for example with Path.is_relative_to(), before calling it.

  9. Question 9 of 10 A script calls sys.exit("disk full") inside a try block that has a finally clause. Which statements are true?

    Choose every answer that is right.

    Show the answer: Question 9 of 10

    Answer:

    • "disk full" is printed on standard error
    • The finally clause runs before the program ends
    • The exit status is 1

    sys.exit() raises SystemExit, so cleanup in finally clauses and with statements still runs. When the argument is a string, Python prints it on standard error and exits with status 1, which callers read as a failure.

  10. Question 10 of 10 By convention, which exit status says that the command line itself was wrong?

    Choose one answer.

    Show the answer: Question 10 of 10

    Answer: 2

    0 means success, 2 a mistake on the command line, and any other number a failure of its own kind that the caller can act on.

Scripts that behave the same on Windows, macOS and Linux Pro: opens with a Pro, Premium or Ultimate pass

Three habits cause many portability bugs: joining paths by hand, splitting PATH on a colon and writing the line ending yourself. This part reproduces each one on any computer, then finds programs and tells the platforms apart with the right call for the job.

In this part:

  • Windows path rules, reproduced on any computer
  • Line endings: when text mode writes one for you
  • Finding programs and telling platforms apart
  • A portability checklist, habit by habit

3 runnable examples (Python) · about 7 minutes

Opening this part with your pass…

This part opens with any MySmartCoPilot pass.

  • Pro pass · 1 week₹79$2.99
  • 30 days₹179$5.99
  • 1 year₹1,699$45

One payment; a pass never renews. The price shown is the total you pay: no fees or charges are added at checkout.

It also opens every other in-depth part in Learn and every Pro tool. Sales are final, except where the law gives you a right to withdraw, for example in the EU and the UK (refund policy).

Environment changes, exit statuses and disk space, measured Pro: opens with a Pro, Premium or Ultimate pass

A script talks to the processes around it through the environment and the exit status, and both have rules that surprise people. This part shows what a child process inherits, why os.environ can be out of date, which exit statuses a parent really receives, and how to check free space before a large job.

In this part:

  • What a child inherits, and what os.environ can miss
  • Exit statuses a parent really sees
  • Checking free space before a large job, with numbers
  • Exercise: a system summary that tests can fake
    • A system summary that tests can fake

4 runnable examples (Python) · 1 exercise with sample tests · about 9 minutes

Opening this part with your pass…

This part opens with any MySmartCoPilot pass.

  • Pro pass · 1 week₹79$2.99
  • 30 days₹179$5.99
  • 1 year₹1,699$45

One payment; a pass never renews. The price shown is the total you pay: no fees or charges are added at checkout.

It also opens every other in-depth part in Learn and every Pro tool. Sales are final, except where the law gives you a right to withdraw, for example in the EU and the UK (refund policy).

Interview questions

  1. Fresher to mid · Warm-up

    What is the difference between sys.platform and platform.system(), and how should a script check which Python version runs it?

    Both describe the operating system, for different readers. sys.platform is an identifier meant for decisions in code: "win32" on Windows, "darwin" on macOS, "linux" on Linux and "emscripten" in the browser. platform.system() returns a name for people, such as "Windows", "Darwin" or "Linux", which suits reports and logs. So code branches on sys.platform, and a report prints platform.system(). For the version, compare sys.version_info, a tuple of numbers, with a tuple: sys.version_info >= (3, 14). Comparing the sys.version string fails, because strings compare character by character and "3.9" sorts after "3.14". Both checks belong at the start of a script, so that it stops with a clear message through sys.exit() on a system or a version it cannot support.

  2. Mid to senior

    A worker thread of a batch job calls sys.exit(1) when it finds corrupt input, yet the job's exit status is 0 and the scheduler reports success. Explain why, and how you would make the job fail correctly.

    Model answer, Pro. Model answers open with any pass; prices are in the notice on this page. First step and follow-ups

  3. Mid to senior

    You review a deployment script written on a Mac that must also run on Windows build servers. It joins paths with f-strings, splits PATH on ":", writes os.linesep to text files and calls rm -rf through a shell. What do you flag, and how do you test the fixes without a Windows machine?

    Model answer, Pro. First step and follow-ups

  4. Mid to senior

    A service loads a C extension that sets TZ with setenv() at start-up. Child processes started by the service see the new TZ, but os.environ["TZ"] still shows the old value. Why, and what do you change?

    Model answer, Pro. First step and follow-ups

Key takeaways

  • A process starts with arguments, a copy of its parent’s environment and a working directory, and hands back one number, its exit status.
  • Test sys.platform in code, compare sys.version_info with tuples, and keep platform for reports.
  • os.environ holds strings: use .get(name, default) for optional settings, [name] for required ones, and convert.
  • A relative name starts in the working directory, so build paths from Path(__file__).resolve().parent.
  • sys.exit("message") prints the message on standard error and exits with status 1, after finally blocks run.

References

Related tools

Report a problem with this lesson

Quick answers and tool search

Type to search tools or to get a quick answer, for example 18% of 2500. Use the up and down arrow keys to move through the results, Enter to choose, and Escape to close.