· about 35 minutes · runs on ubuntu-26.04-devops · unrated
An unrated lab. It runs on your machine with no account and no network, and everything about it — the faults, the checks, the hints and the reference solution — is in the repository. An attempt on it is recorded on your profile and never moves a rating: only rated labs do. Rated and unrated labs.
/opt/digest/digest.py reads the day's events from /srv/digest/events.json and writes a one-line
digest to /var/lib/digest/today.txt. digest.service runs it after boot.
Since a colleague added a small helper for the internal calendar, every run fails with a traceback
that makes no sense: AttributeError: module 'calendar' has no attribute 'monthrange'. Somebody
added WorkingDirectory=/opt/digest to the unit last week hoping it would help; it changed
nothing.
What is expected, and graded — the grader runs digest.py itself, through the DIGEST_EVENTS and
DIGEST_OUT variables the script already reads:
/opt/digest, the program writes the digest and exits 0.calendar, json or logging in a program started from /opt/digest gives the
module from Python's own library.digest.service succeeds and the digest holds today's events — and still does after a reboot.You have root through sudo. The helper's own function must keep working: the digest names the
number of days in the month.
The machine is checked, rebooted, and checked again. A check passes only if it passes both times.
| Check | Objective |
|---|---|
| 01_runs_from_its_own_directory | Keep a program's own modules from standing in for the standard library |
| 02_runs_from_anywhere | Run a program from a systemd unit without depending on the caller's directory |
| 03_the_stdlib_is_not_shadowed | Know where Python looks for a module, and in which order |
| 04_the_service_writes_its_digest | Run a program from a systemd unit without depending on the caller's directory |
Where the lab's hints send you, level by level, as you ask for them (h, then l opens a journal section in the TUI).
man 5 systemd.execman 1 journalctlman 5 systemd.service4 questions on the same topic, in the lab's Theory tab. They never affect the lab's grade. Three of them, to answer here:
`/opt/digest/digest.py` starts with `import calendar`, and `/opt/digest/calendar.py` exists. The program is started with `cd /tmp && python3 /opt/digest/digest.py`. Which file is imported?
/opt/digest/calendar.py
For a script, sys.path[0] is the directory of the script — /opt/digest — not the working directory, so the file beside the script wins over the standard library wherever the program is started from. That is also why WorkingDirectory= in a unit changes nothing.
https://docs.python.org/3/tutorial/modules.html#the-module-search-path
What does this print?
import pathlib, subprocess, sys, tempfile
d = pathlib.Path(tempfile.mkdtemp())
(d / "calendar.py").write_text("VALUE = 1\n")
(d / "app.py").write_text("import calendar; print(hasattr(calendar, 'monthrange'))\n")
print(subprocess.run([sys.executable, str(d / "app.py")],
cwd="/", capture_output=True, text=True).stdout.strip())
False
The child runs with / as its working directory, but sys.path[0] is the script's own directory, where calendar.py is — so the import finds that file, which has no monthrange, and hasattr is False. Renaming the helper, or running with -P / PYTHONSAFEPATH=1, gives True.
https://docs.python.org/3/library/sys.html#sys.path · executed in a sandbox
Which of these modules cannot be shadowed by a file of the same name beside your script?
sys
sys is compiled into the interpreter (sys.builtin_module_names), so importing it never touches sys.path. json, logging and calendar are ordinary Python files in the standard library and are found on the path, after the script's own directory.
https://docs.python.org/3/library/sys.html#sys.builtin_module_names