Python Creating Modules

In the last lesson you learned the Import Statement. There you pulled in code that other people wrote. Now we flip it around. What if you want to write a piece of code once and use it in many places? You make your own module. And it is simpler than it sounds. A module is just a Python file you import.

🤔 Why Create Your Own Module?

Picture this. You write a handy function that greets a user. It sits in your file and works great. Then you start a second program that also needs to greet users. So you copy that function over. Then a third program needs it too. So you copy it again.

Here is the pain. The same function now lives in three files. One day you improve it. And now you have to fix it in all three places. Miss one, and that program is out of date.

The fix is a module. A module is a Python file that holds code you want to reuse. You write the function once in its own file. Then any other file can import it. Change it in one place, and every program that imports it gets the update.

🧩 What Counts as a Module?

Here is the part that surprises people. You have already been making modules without knowing it.

Every .py file you write is a module. That is the whole secret. There is no special keyword. There is no setup. The moment you save a Python file, another Python file sitting next to it can import it.

So a module is just a normal Python file. The name of the module is the file name without the .py ending. A file called my_utils.py is a module named my_utils.

🛠️ Making Your First Module

Let’s build one. We will make a small file with a function inside it. Then we will use that function from a second file.

The key rule is this. Both files must sit in the same folder. That way the second file can find the first one easily.

  1. Create the module file

    Make a file called my_utils.py. Put one function inside it. This function takes a name and returns a greeting.

    my_utils.py
    def greet(name):
    return f"Hello, {name}! Welcome aboard."
  2. Create the main file

    In the same folder, make a second file called main.py. This is the program you will actually run.

    main.py
    from my_utils import greet
    message = greet("Alex")
    print(message)
  3. Run the main file

    Run main.py from your terminal. You do not run my_utils.py. You run the file that imports it.

    Terminal window
    python main.py

Here is what shows up.

Output

Hello, Alex! Welcome aboard.

Look at what happened. The greet function never appears in main.py. It lives in my_utils.py. But the line from my_utils import greet reached into that file and pulled the function out, ready to use.

📥 Reading the Import Line

That one line does a lot. So let’s slow down and read it piece by piece.

from my_utils import greet

Here is how Python reads it:

  • from my_utils means “go look in the file my_utils.py”. Notice there is no .py here. You use just the module name.
  • import greet means “bring the greet function into this file”.
  • After this line, you can call greet(...) as if you had written it right here in main.py.

You can pull in more than one thing too. Say my_utils.py also had a farewell function. You would just list both, with a comma between them.

from my_utils import greet, farewell

Now both functions are available in main.py. One module, many reusable pieces.

⚙️ The if __name__ == "__main__" Guard

Now we hit a real-world problem. And Python has a neat answer for it.

Say you are writing my_utils.py. While building the greet function, you want to test it. So you add a print at the bottom to check it works.

my_utils.py
def greet(name):
return f"Hello, {name}! Welcome aboard."
print(greet("Riya")) # quick test

Run my_utils.py directly and you see your test line. Great. But now run main.py, which imports this file. Watch what happens.

Output

Hello, Riya! Welcome aboard.
Hello, Alex! Welcome aboard.

See the problem? That first line is the leftover test. When Python imports a file, it runs every line in it from top to bottom. That includes the print. So your test code leaked into a program that just wanted the function.

The fix is a special check. We wrap the test code in this guard.

my_utils.py
def greet(name):
return f"Hello, {name}! Welcome aboard."
if __name__ == "__main__":
print(greet("Riya")) # only runs when this file is run directly

Run main.py again and the stray line is gone.

Output

Hello, Alex! Welcome aboard.

So what is this __name__ thing? It is a built-in variable that Python sets for every file. Its value depends on how the file was started:

  • When you run a file directly, like python my_utils.py, Python sets that file’s __name__ to the text "__main__".
  • When a file is imported by another file, Python sets its __name__ to the module name instead, like "my_utils".

So the line if __name__ == "__main__": is really asking one plain question. “Am I the file being run right now, or was I imported?” The code inside the guard runs only when the file is run directly. On an import, the check is false. So that code is skipped.

Note

A simple way to hold it in your head. Code inside if __name__ == "__main__": is the “run me on my own” code. Everything outside it, like your functions, is the “use me from anywhere” code.

⚠️ Common Mistakes

A few things trip people up the first time they split code into files. Watch for these.

  • Writing .py in the import. The import uses the module name, not the file name.
# ❌ Avoid: do not add .py
from my_utils.py import greet
# ✅ Good: just the module name
from my_utils import greet
  • Putting the files in different folders. If main.py and my_utils.py are not in the same folder, the simple import will not find the module and you get a ModuleNotFoundError.

  • Running the module instead of the main file. You run the file that imports, which is main.py. Running my_utils.py on its own only triggers its own if __name__ == "__main__": block.

  • Leaving test code unguarded at the bottom of a module. Without the guard, that code runs every time the module is imported. And you almost never want that.

✅ Best Practices

Keep these habits and your modules stay clean and easy to reuse.

  • Give modules clear, lowercase names with snake_case, like my_utils.py or string_helpers.py. Skip spaces and capital letters.
  • Put related functions together in one module. A file of text helpers, a file of math helpers, and so on.
  • Always wrap any test or demo code in if __name__ == "__main__":. That way importing the file stays quiet.
  • Keep each module focused on one job. A module that tries to do everything gets hard to reuse.

🧩 What You’ve Learned

You can now split your code across files and reuse it cleanly. Here is the short version.

  • ✅ A module is just a .py file, and its name is the file name without the .py.
  • ✅ You import a function from your own module with from module_name import function_name.
  • ✅ Both files must sit in the same folder for the simple import to work.
  • ✅ Importing a file runs every line in it from top to bottom.
  • if __name__ == "__main__": holds code that runs only when the file is run directly, not when it is imported.

Check Your Knowledge

Test what you learned. Pick an answer for each question, then click Check.

  1. 1

    What is a Python module?

    Why: Every .py file is a module. Its module name is the file name without the .py ending.

  2. 2

    How do you bring the greet function from my_utils.py into main.py?

    Why: You use the module name without .py: from my_utils import greet.

  3. 3

    When does code inside if __name__ == "__main__": run?

    Why: Python sets __name__ to "__main__" only for the file being run directly, so the guarded code is skipped on import.

  4. 4

    What happens when you import a Python file?

    Why: Importing runs the whole file top to bottom, which is why unguarded test code at the bottom will also run.

🚀 What’s Next?

You can build and reuse single modules now. Next we group several related modules together into a tidy bundle you can share and import as a whole.

Python Packages

Share & Connect