Modules in Python
So far every program of yours has fitted into a single file, and that was enough. But one day you write a function that would come in handy in the next task too, and the only way to move it there is to copy it. Copy it into three scripts, find a bug, and you are fixing it in three places.
So we need a way to keep code in a separate file and pull only what we need out of it. A file like that is called a module.
You already use modules
The line import math has come up in the chapters on libraries. Let's look closer at what it actually does.
Python 3.13import math print(math.sqrt(144))12.0print(type(math))<class 'module'>
import doesn't paste somebody else's file into yours. It creates a module object and puts it in a variable called math. From then on math.sqrt is an ordinary attribute access, exactly like "text".upper().
Creating your own module
Now let's make such a file ourselves. Say we have a small script that works out prices: it adds VAT and applies discounts. The calculation itself goes into prices.py, while main.py keeps only the printing of results:
1import prices2 3print(prices.with_vat(100)) # 120.04print(prices.discount(1000, 15)) # 850.05print(prices.VAT) # 0.26 main.py says import prices, and Python finds prices.py in the same folder. The module name comes from the file name: drop the .py and you get prices. That is all the import needs.
Since the module name is the file name, name your files in snake_case: user_interface.py, not UserInterface.py. And not random.py: a file named after a standard library module shadows the real one.
A module's code runs exactly once
On an import Python executes the file top to bottom. In boot.py below the print sits at the top level, not inside a function, so it fires on import. Let's import that module on two consecutive lines:
1import boot2import boot3 4print("and there were two import lines")5 boot.py is running and there were two import lines
Even though there were two import lines, the file ran once: Python remembers the modules it has already finished and on a repeated import hands back the same object. Hence the practical takeaway: the top level of a module holds definitions, not actions — whatever is written there runs on the very first import, even if none of its functions are ever used.
from ... import: the name moves in with you
Typing prices. before every call gets tiring. The from ... import form takes a specific name out of the module and puts it straight into your program. In the example below both import forms sit side by side on purpose, so that the last line can compare the result — you wouldn't write it that way in ordinary code.
1import prices2from prices import with_vat3 4print(with_vat(100)) # 120.05print(with_vat is prices.with_vat) # True6 The last line is the important one. No copy of the function was made: with_vat and prices.with_vat are two names for one object. from ... import isn't "another way to import", it's an extra step: first the module is imported in full (with all its code), then one of its names is copied into your namespace.
So you have three forms, and you choose between them like this:
-
You need many names from the module, or it matters where a name came from — keep the prefix:
Python 3.13import prices print(prices.with_vat(100)) -
You need two or three functions and call them often — take them by name, the code gets shorter:
Python 3.13from prices import with_vat, discount print(with_vat(100)) -
The module name is long or already taken by a variable of yours — bring it in under a short name:
Python 3.13import prices as p print(p.with_vat(100))
That last form is exactly why people write import pandas as pd.
Telling a run apart from an import
As we saw, an import executes the whole code of a module. So the code inside prices.py runs in both cases:
python prices.py # launching the module itself python main.py # launching the program that imports it
But sometimes code is only wanted when the file itself is launched. A check along the lines of "do the functions compute the right thing", say: handy for the author, pure noise for whoever imports the module.
The __name__ variable, which every module has, is what tells the two apart. On an import it holds the module's name, here "prices". In a file that was launched directly it always holds "__main__". So a condition like this is true only on a direct launch:
Python 3.13if __name__ == "__main__": print("check:", with_vat(100))
In prices.py below that check sits at the very bottom, while main.py on the next tab simply imports the module:
1"""Price calculations: VAT and discounts."""2 3VAT = 0.24 5 6def with_vat(price):7 """Price including VAT."""8 return round(price * (1 + VAT), 2)9 10 11def discount(price, percent):12 """Price after a percentage discount."""13 return round(price * (1 - percent / 100), 2)14 15 16if __name__ == "__main__":17 print("check:", with_vat(100))18 total: 120.0
We launched main.py, and the output holds only its own line: __name__ inside prices.py equals "prices", the condition is false, the check stayed quiet. Launching the module directly would have printed check: 120.0.
This is how one file plays two roles: a set of functions for other code, and a standalone program. That block is where you put everything that must not happen on import: starting the program, parsing command-line arguments, checks like ours.
