Project Structure

As programs grow, putting everything in one file gets hard to manage. This guide covers patterns for organizing Python projects into clear, maintainable pieces.

The main() Pattern

Define a main() function that ties your program together, then call it at the bottom of the file. This gives your program a clear starting point that reads like a story:

def display_greeting(name):
    print("Welcome, " + name + "!")

def main():
    name = input("Enter your name: ")
    display_greeting(name)
    print("Session started.")

main()

Without main(), your top-level code runs line by line, scattered between function definitions. With main(), the flow is obvious: get a name, greet, start session.

Why Use main()?

  • Readability — one function tells you what the whole program does
  • Organization — separates setup/orchestration from helper logic
  • Control — code inside main() only runs when you call it, not on import

Splitting into Multiple Files

When a project has several functions, move helpers into their own file:

my-project/
    main.py
    helpers.py
    data/
        agents.txt

helpers.py holds reusable functions:

# helpers.py

def load_agents(filename):
    agents = []
    with open(filename, "r") as file:
        for line in file:
            parts = line.strip().split(",")
            agent = {"name": parts[0], "department": parts[1]}
            agents.append(agent)
    return agents

def display_agent(agent):
    print(agent["name"] + " — " + agent["department"])

main.py imports and uses them:

# main.py
from helpers import load_agents, display_agent

def main():
    agents = load_agents("data/agents.txt")
    for agent in agents:
        display_agent(agent)

main()

The __name__ Guard

When Python runs a file directly, it sets a special variable __name__ to "__main__". When a file is imported, __name__ is set to the file's module name instead.

This matters because any code at the top level of a file runs on import. The guard prevents that:

# helpers.py

def greet(name):
    return "Hello, " + name + "!"

if __name__ == "__main__":
    print(greet("test"))

Run helpers.py directly:

$ python helpers.py
Hello, test!

Import helpers from another file:

# main.py
from helpers import greet

print(greet("Alice"))
$ python main.py
Hello, Alice!

The test line inside the guard does not run when main.py imports helpers. Without the guard, you would see both "Hello, test!" and "Hello, Alice!".

When to Use the Guard

Put code inside if __name__ == "__main__": when:

  • You have test or demo code in a helper file
  • You want to run a file on its own and import it from elsewhere
  • You want to keep your main() call from running on import

A typical helper file looks like this:

# helpers.py

def load_data(filename):
    # ... loading logic ...
    return data

def process_data(data):
    # ... processing logic ...
    return results

if __name__ == "__main__":
    test_data = load_data("test.txt")
    print(process_data(test_data))

And a typical entry point:

# main.py
from helpers import load_data, process_data

def main():
    data = load_data("data/records.txt")
    results = process_data(data)
    print(results)

if __name__ == "__main__":
    main()

Putting It All Together

Here is a complete two-file project:

archive-audit/
    main.py
    helpers.py
    data/
        agents.txt
# helpers.py

def load_agents(filename):
    agents = []
    with open(filename, "r") as file:
        for line in file:
            parts = line.strip().split(",")
            agents.append({
                "name": parts[0],
                "department": parts[1],
                "score": int(parts[2])
            })
    return agents

def get_active(agents):
    results = []
    for agent in agents:
        if agent["score"] >= 70:
            results.append(agent)
    return results

def save_report(filename, agents):
    with open(filename, "w") as file:
        for agent in agents:
            file.write(agent["name"] + ": " + str(agent["score"]) + "\n")

if __name__ == "__main__":
    test_agents = load_agents("data/agents.txt")
    print("Loaded " + str(len(test_agents)) + " agents")
# main.py
from helpers import load_agents, get_active, save_report

def main():
    agents = load_agents("data/agents.txt")
    active = get_active(agents)
    save_report("data/report.txt", active)
    print("Report saved: " + str(len(active)) + " active agents")

if __name__ == "__main__":
    main()

Common Mistakes

Forgetting the guard in a helper file

# helpers.py

def greet(name):
    return "Hello, " + name + "!"

print(greet("test"))  # Runs every time helpers is imported!

Running the wrong file

# Wrong — runs helpers.py directly, not your main program
python helpers.py

# Right — run the entry point
python main.py

Putting main() at the top level without the guard

# This runs on import too
def main():
    print("Starting...")

main()  # Always runs, even when imported

# Better
if __name__ == "__main__":
    main()  # Only runs when this file is executed directly