Persisting and Sharing Data

Imports, Libraries, and Documentation


Learning Objectives

  • You can define a function in one source file and use it from another.
  • You can keep a module import separate from starting a program.
  • You can import and use standard-library functions by consulting their documented inputs, outputs, and options.
  • You can distinguish standard-library modules from external packages.
  • You can investigate a file-location problem without guessing where the program runs.

You have been using code supplied by Python since Part 1. Functions such as len are available immediately. Other functionality is organized into modules that a program imports when it needs them.

The earlier game exercises already contained imports. This chapter makes that part of the framework less mysterious.

Use a Module by Name

No files opened Select a file to edit

os is a module from Python’s standard library. The call os.getcwd() returns the current working directory as a string. It is useful when a relative file path appears not to work.

import os makes the module available under the name os. The dot identifies functionality belonging to that module. It does not mean the function is implemented inside your source file.

The output depends on where your program runs. Compare it with the folder containing the file you intended to open. Predict whether calling os.getcwd() again changes that folder, then try it: this call reports a location without moving the program.

The supplied check files use another import form:

from main import read_message

Here main refers to main.py in the exercise. This line makes its read_message function available under that name, so the checks can call read_message(...). It does not run the function by itself. You can use this same mechanism to share your own functions between an application and its checks.

Loading main.py does execute any statements outside its function definitions. Keep its file operations inside the functions and put temporary calls in check.py, so importing the functions does not also read or overwrite a file.

Standard Libraries and External Packages

The standard library is supplied with Python. This part uses os, csv, and json from that library.

Pyxel is an external package used by the graphical game environment. Importing an external package requires that it already be available in that environment. An import statement does not itself download or install it.

Do not create files named csv.py, json.py, or os.py for these exercises. A local file with a library’s name can hide the module you intended to import. Choose a task name such as catalogue_report.py.

A source file you write can also be a module. Start with two small files before considering larger program structures in Part 6.

Put a Reusable Rule in Its Own File

Word Practice will compare a typed answer with an expected translation. Both the game and a check file need the same rule. Put it in word_rules.py.

The editor below supplies three neighboring files. Open word_app.py and Run. Predict the output, then run check_words.py instead.

No files opened Select a file to edit

Running the application prints True. Running the check file prints only Checks passed.. Both callers use the one definition in word_rules.py. The name in from word_rules import answer_matches has no .py suffix.

The comparison strips surrounding whitespace and ignores capitalization. It keeps accents meaningful: "yo" is not the same word as "yö".

Import Definitions Without Starting the Application

A module’s top-level statements run when it is first imported. Defining a function makes the function available; it does not call its body.

The last two lines of word_app.py control when its demonstration runs:

if __name__ == "__main__":
main()

When Python runs this file directly, __name__ is "__main__". When check_words.py imports word_app, it has the module’s name instead, so the conditional skips main().

Remove the condition temporarily, leaving an unindented main() call. Predict the additional output when running check_words.py, then try it. Restore the guard afterward.

The guard protects the statements inside it. It does not prevent other top-level statements from running. Keep prompting, file writes, and graphical startup inside functions called from the guarded entry point.

Now download the following exercise and move a supplied rule into its own module. Edit main.py and word_rules.py, then run check.py for assertions and main.py for the application output. The handout gives the terminal and submission commands.

Share a word rule between files

0 / 10 points

Move the supplied answer_matches(response, target) function from main.py into word_rules.py, and import it in main.py so the existing main() uses the moved function. You may import the module or the named function.

Keep the rule unchanged: both inputs are strings; ignore surrounding whitespace and capitalization, but keep accents meaningful. Return a boolean without printing. The function belongs in word_rules.py, with no second definition in main.py.

Running main.py prints True once. Importing either module must not print, ask for input, or access data files. Keep the guarded call at the bottom of main.py.

Work locally

Download this exercise with the Aalto OpenCS IDE plugin, or use Download starter code below and extract the ZIP into its own folder inside programming-practice. Open that exercise folder in your IDE. Keep each exercise in a separate folder.

FileRole
main.pyReplace its answer_matches definition with an import; keep the application and guarded call.
word_rules.pyMove the answer_matches definition here.
check.pySupplied assertions that import the rule; add your own cases here.

Save your changes, then open the IDE terminal in this exercise folder: dir on Windows or ls on macOS/Linux should show the files above. Relative paths in the checks start from this folder. Run:

SystemRun the checks
Windowspy check.py
macOS/Linuxpython3 check.py

Use python instead if that is your working Python command. Successful supplied checks print Checks passed.. Read any failed assertion or traceback, fix your code, and rerun the checks. You may extend check.py; use separate data files for extra cases so the supplied samples retain their contents.

The checks include answer_matches("YÖ", "yö") == True and answer_matches("yo", "yö") == False. Also run py main.py on Windows or python3 main.py on macOS/Linux: the application should print True once. This is separate from running the assertions.

Submit your solution

Save your files. Submit using Submit Current Exercise in the IDE plugin, review the file list, and confirm Submit. Alternatively, create a ZIP from the exercise folder:

SystemCommand
Windowspy -m zipfile -c submission.zip main.py word_rules.py check.py
macOS/Linuxpython3 -m zipfile -c submission.zip main.py word_rules.py check.py

Upload submission.zip below and press Submit. The listed files must be at the archive’s top level, without an enclosing folder. Include the supplied support and sample files; leave out generated outputs, .venv, and __pycache__. Read the grading feedback after submitting. The grader also uses its own inputs; passing the sample checks alone does not establish the whole contract.

Source Files and Data Files

These files have different roles:

FileHow the program uses it
word_rules.pyImport Python definitions
word_app.pyRun the application
check_words.pyRun assertions against the same definitions
vocabulary.csvOpen and parse vocabulary data in a later chapter

Importing a module is not how we read arbitrary data. The next chapters use open and format libraries for that work.

Locally, keep related files in one project folder and run the intended entry file from its terminal: for example, python3 word_app.py or python3 check_words.py. Use py or python if that is your Python command. An import does not change the terminal’s current working directory.

Read the Interface Before Guessing

A library function has a contract, just as your functions did in Part 3. Documentation describes the name, arguments, returned value, effects, and relevant failure cases.

For example, a game framework may use:

import random
value = random.randint(1, 6)

The documented endpoints are inclusive, so this call can produce either 1 or 6. We can test the range of a generated value, but repeatedly seeing only some values would not tell us the complete contract. The documentation supplies that rule.

When reading a function description, ask:

What does the function receive?
What does it return or change?
Which assumptions and exceptional cases matter for this use?

Do not try to learn every option before making the first call. Start with the options the task needs.

Keyword Arguments Make Choices Visible

You have already used keyword arguments:

with open("practice_note.txt", "r", encoding="utf-8") as file:
text = file.read()

encoding names the option being supplied. In a file-format operation, a keyword might instead specify field names or indentation.

A keyword argument does not create a local variable with that name in your program. It associates an argument with a named parameter of the function or operation being called.

Documentation signatures can also contain notation you have not learned. You do not need to reproduce the entire signature to call the function. Use the documented examples and the parameter descriptions to identify the required arguments and relevant options.

Check the File Location

When a function receives a folder and a filename separately, use os.path.join to form the path:

No files opened Select a file to edit

os.path.join uses the path convention of the current environment. It does not create a folder or change the working directory. The next file-writing task receives an existing folder from its caller.

Place a note

0 / 15 points

Write write_note(folder, filename, message). Folder is the path of an existing directory; filename is a plain filename without directory separators. Use os.path.join to form the destination. Write message exactly as UTF-8 text, replacing previous contents, then return the resulting path string. Use newline="" when opening the file so its line endings remain unchanged on every operating system. Do not print or change the working directory. Empty messages are permitted.

Use the documented os.path.join(folder, filename) interface introduced in the text. The caller chooses the folder; do not assume it is the program’s current folder.

Work locally

Download this exercise with the Aalto OpenCS IDE plugin, or use Download starter code below and extract the ZIP into its own folder inside programming-practice. Open that exercise folder in your IDE. Keep each exercise in a separate folder.

FileRole
main.pyWrite write_note(folder, filename, message) here.
check.pySupplied checks that write and read a note; extend them.

Save your changes, then open the IDE terminal in this exercise folder: dir on Windows or ls on macOS/Linux should show the files above. Relative paths in the checks start from this folder. Run:

SystemRun the checks
Windowspy check.py
macOS/Linuxpython3 check.py

Use python instead if that is your working Python command. Successful supplied checks print Checks passed.. Read any failed assertion or traceback, fix your code, and rerun the checks. You may extend check.py; use separate data files for extra cases so the supplied samples retain their contents.

The supplied check calls write_note with the current folder, "practice_note.txt", and "A note\n", then reads the returned path. The output file remains in the exercise folder. Add a check using another existing folder to test that the function uses its folder argument.

main.py defines functions; running it alone produces no output. check.py imports and calls those functions. Keep file operations inside the functions, with test calls in check.py, so importing main.py does not read or write data files or ask for input.

Submit your solution

Save your files. Submit using Submit Current Exercise in the IDE plugin, review the file list, and confirm Submit. Alternatively, create a ZIP from the exercise folder:

SystemCommand
Windowspy -m zipfile -c submission.zip main.py check.py
macOS/Linuxpython3 -m zipfile -c submission.zip main.py check.py

Upload submission.zip below and press Submit. The listed files must be at the archive’s top level, without an enclosing folder. Include the supplied support and sample files; leave out generated outputs, .venv, and __pycache__. Read the grading feedback after submitting. The grader also uses its own inputs; passing the sample checks alone does not establish the whole contract.

Now check the difference between a documented guarantee and the result of one experiment.

Documentation and Small Experiments Work Together

Documentation explains intended behavior. A small experiment checks your understanding of it in the environment you are using.

The two sources of evidence have different roles. A successful experiment with one value does not establish every boundary case. Reading an example does not ensure that your own file has the expected shape.

For the substantial verification activity later in this part, you will use both documentation and a controlled file to evaluate a library claim. There is no need to request or trust an AI explanation before every library call.

Documentation for This Part

These are references to consult for a particular question, not additional chapters to read in full.

Check Your Understanding

  1. Why does importing a package not install it?
  2. Why can a local file named json.py cause trouble?
  3. What can documentation tell you that one successful experiment cannot?
  4. Why does importing the guarded application not run its demonstration?
  5. How does a source module differ from a vocabulary data file?