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