In most cases, avoid def main() in Python — It’s not Java or C++
A pattern that keeps appearing in Python scripts, tutorials, and AI-generated code:
def main():
do_stuff()
if __name__ == "__main__":
main()
This is cargo-culted from C and Java, where a main() function is a syntactic requirement. Python has no such rule. The above is functionally identical to:
if __name__ == "__main__":
do_stuff()
When def main() actually makes sense
There is one legitimate use case: when you need a named entry point for Python packaging. If your pyproject.toml defines a console script, it must reference a callable:
[project.scripts]
mytool = "mypackage.cli:main"
Here, def main() earns its place. But this is a specific packaging concern — not a general best practice for every script you write.
Why does this keep spreading?
- Language habits: Developers coming from C, Java, or Go carry the pattern into Python without questioning it.
- LLM training data: Models are trained on GitHub, which is full of this pattern, so they reproduce it automatically.
- Misunderstood testability: Some argue
def main()makes code more testable. It doesn’t — if your logic is a monolith insidemain(), it’s just as hard to test. Real testability comes from decomposing logic into focused, well-scoped functions. - Cargo-culting tutorials: Many “professional Python” guides include it as boilerplate, implying it’s idiomatic when it’s really just familiar.
The Pythonic way
Write clean, decomposed functions. Use if __name__ == "__main__": as a lightweight guard when you need it. That’s it.
def process_data(data):
...
def save_results(results):
...
if __name__ == "__main__":
data = load()
results = process_data(data)
save_results(results)