{"id":"own-modules-main","slug":"main-block","title":"The main block, explained","text":"Since part 4, the starter code of function tasks has ended with a block like this:\n\n```python\nif __name__ == \"__main__\":\n    print(mean([1, 2, 3]))\n```\n\nNow that you write modules of your own, you can see what it does and why it's there.\n\n### Importing runs the module\n\nWhen Python imports a module, it runs the module's file from top to bottom. A `def` only defines a function, but any other code at the top level of the file runs too. So test prints left in a module show up in every program that imports it:\n\n```python\nimport tools\n\nprint(\"The main program starts\")\nprint(tools.shout(\"hello\"))\n# ==== tools.py ====\ndef shout(text):\n    return text.upper() + \"!\"\n\n\nprint(\"Testing shout:\", shout(\"test\"))\n```\n\n```output\nTesting shout: TEST!\nThe main program starts\nHELLO!\n```\n\nThe first line isn't the main program's at all: it's the module's own test, run by the `import`.\n\n### The variable __name__\n\nPython gives every module a variable called **`__name__`**. In the file Python started, the program itself, its value is `\"__main__\"`. In a module that was imported, it's the module's name:\n\n```python\nimport tools\n\nprint(\"In main.py, __name__ is\", __name__)\n# ==== tools.py ====\nprint(\"In tools.py, __name__ is\", __name__)\n```\n\n```output\nIn tools.py, __name__ is tools\nIn main.py, __name__ is __main__\n```\n\n### The main block\n\nSo `if __name__ == \"__main__\":` means \"only when this file is the program that was started\". Put a module's tests under it, and they run when you run the module's file itself, but stay quiet when another program imports it:\n\n```python\nimport tools\n\nprint(tools.shout(\"hello\"))\n# ==== tools.py ====\ndef shout(text):\n    return text.upper() + \"!\"\n\n\nif __name__ == \"__main__\":\n    print(\"Testing shout:\", shout(\"test\"))\n```\n\n```output\nHELLO!\n```\n\nThe block is called the **main block**. It's a convention, not a rule of the language, but nearly every Python module that has code to test or run uses it.\n\n### And the checks on this site\n\nThe checks for function tasks do exactly what `import` does: they load your program as a module, so its `__name__` isn't `\"__main__\"` and the main block is skipped. Then they call your functions themselves. That's why your own test calls belong in the main block: there they help you while you write the function, and they don't get mixed into what the checks see. A test print outside the block would run at every check.\n","task":"The module `temperature.py` has two test prints at its top level, and they end up in the output of `main.py`. Move them under a main block, so they don't run when the module is imported and `main.py` prints only its own lines:\n\n```\nTemperature in Celsius: -5\n23.0 F\nfreezing\n```\n","kind":"code","seed":"# ==== main.py ====\nimport temperature\n\nreading = float(input(\"Temperature in Celsius: \"))\nprint(f\"{temperature.to_fahrenheit(reading):.1f} F\")\nprint(temperature.describe(reading))\n\n# ==== temperature.py ====\ndef to_fahrenheit(celsius: float) -> float:\n    return celsius * 9 / 5 + 32\n\n\ndef describe(celsius: float) -> str:\n    if celsius < 0:\n        return \"freezing\"\n    if celsius < 20:\n        return \"cool\"\n    return \"warm\"\n\n\nprint(to_fahrenheit(100))\nprint(describe(25))\n","solution":"# ==== main.py ====\nimport temperature\n\nreading = float(input(\"Temperature in Celsius: \"))\nprint(f\"{temperature.to_fahrenheit(reading):.1f} F\")\nprint(temperature.describe(reading))\n\n# ==== temperature.py ====\ndef to_fahrenheit(celsius: float) -> float:\n    return celsius * 9 / 5 + 32\n\n\ndef describe(celsius: float) -> str:\n    if celsius < 0:\n        return \"freezing\"\n    if celsius < 20:\n        return \"cool\"\n    return \"warm\"\n\n\nif __name__ == \"__main__\":\n    print(to_fahrenheit(100))\n    print(describe(25))\n","hints":["Check it and look at the output. The first two lines come from `temperature.py`, which runs when `main.py` imports it.","Add the line `if __name__ == \"__main__\":` above the two prints in `temperature.py`, and indent the prints under it. Keep the tests; just move them into the block."],"tests":[{"name":"Test 1","stdin":"-5\n","expect":"Temperature in Celsius: -5\n23.0 F\nfreezing","hidden":false},{"name":"Test 2","stdin":"21.5\n","expect":"Temperature in Celsius: 21.5\n70.7 F\nwarm","hidden":true},{"name":"Test 3","stdin":"12\n","expect":"Temperature in Celsius: 12\n53.6 F\ncool","hidden":true}],"require":[{"pattern":"if\\s+__name__\\s*==\\s*[\"']__main__[\"']\\s*:\\n(\\s+print\\(.*\\)\\n){2}","raw":true,"message":"Keep the two test prints, indented under `if __name__ == \"__main__\":` in `temperature.py`."}],"forbid":[],"more":[{"task":"What does this program print? Type each line it prints.\n","kind":"predict","seed":"# ==== main.py ====\nimport helper\n\nprint(\"main:\", __name__)\nhelper.show()\n\n# ==== helper.py ====\ndef show():\n    print(\"show:\", __name__)\n\n\nprint(\"loading:\", __name__)\n","solution":"# ==== main.py ====\nimport helper\n\nprint(\"main:\", __name__)\nhelper.show()\n\n# ==== helper.py ====\ndef show():\n    print(\"show:\", __name__)\n\n\nprint(\"loading:\", __name__)\n","hints":["The `import` on the first line runs `helper.py` from top to bottom before anything else in `main.py`.","In `main.py`, the file Python started, `__name__` is `__main__`.","`show` is defined in `helper.py`, so the `__name__` it prints is that module's: `helper`."],"tests":[{"name":"Output","stdin":"","expect":"loading: helper\nmain: __main__\nshow: helper","hidden":false}],"require":[],"forbid":[],"lines":["loading: helper","main: __main__","show: helper"]},{"task":"`main.py` is ready, and `textstats.py` is empty. Write the module:\n\n- `word_count(text: str) -> int` returns the number of words in the text (the words are separated by spaces).\n- `longest_word(text: str) -> str` returns the longest word, or the first of them if several are equally long.\n- A main block at the end that tests both functions with a print each. It must not run when `main.py` imports the module.\n\nFor example:\n\n```\nText: the quick brown fox jumps\nWords: 5\nLongest word: quick\n```\n","kind":"code","seed":"# ==== main.py ====\nimport textstats\n\nline = input(\"Text: \")\nprint(\"Words:\", textstats.word_count(line))\nprint(\"Longest word:\", textstats.longest_word(line))\n\n# ==== textstats.py ====\n# Write the functions word_count and longest_word here, and a main block that tests them.\n","solution":"# ==== main.py ====\nimport textstats\n\nline = input(\"Text: \")\nprint(\"Words:\", textstats.word_count(line))\nprint(\"Longest word:\", textstats.longest_word(line))\n\n# ==== textstats.py ====\n# Write the functions word_count and longest_word here, and a main block that tests them.\ndef word_count(text: str) -> int:\n    return len(text.split())\n\n\ndef longest_word(text: str) -> str:\n    longest = \"\"\n    for word in text.split():\n        if len(word) > len(longest):\n            longest = word\n    return longest\n\n\nif __name__ == \"__main__\":\n    print(word_count(\"one two three\"))\n    print(longest_word(\"a bb ccc dd\"))\n","hints":["`text.split()` gives the words as a list, so the word count is its length.","For the longest word, go through the words and keep the longest so far. Replace it only when a word is strictly longer, so the first of equally long words stays.","End the file with `if __name__ == \"__main__\":` and two indented test prints."],"tests":[{"name":"Test 1","stdin":"the quick brown fox jumps\n","expect":"Text: the quick brown fox jumps\nWords: 5\nLongest word: quick","hidden":false},{"name":"Test 2","stdin":"modules make programs easier to read\n","expect":"Text: modules make programs easier to read\nWords: 6\nLongest word: programs","hidden":true},{"name":"Test 3","stdin":"one\n","expect":"Text: one\nWords: 1\nLongest word: one","hidden":true},{"name":"Test 4","stdin":"ab cd ef\n","expect":"Text: ab cd ef\nWords: 3\nLongest word: ab","hidden":true}],"require":[{"pattern":"if\\s+__name__\\s*==\\s*[\"']__main__[\"']\\s*[:]","raw":true,"message":"End `textstats.py` with a main block, `if __name__ == \"__main__\":`, that tests the functions."}],"forbid":[]}]}