Python tutorials > Modules and Packages > Packages > What is Python project structure?
What is Python project structure?
Understanding the structure of a Python project is crucial for maintainability, collaboration, and overall code quality. A well-defined project structure helps organize code, manage dependencies, and ensures that your project can scale effectively. This tutorial covers the common elements of a Python project structure and best practices for organizing your code.
Basic Project Layout
A basic Python project structure typically includes the following elements:
src/
or Package Directory: A directory (often named src
or the name of your main package) containing the project's Python modules and sub-packages. This helps separate source code from other files.tests/
Directory: A directory containing test suites for your project.README.md
: A file containing information about your project, including its purpose, installation instructions, and usage examples.LICENSE
: A file specifying the license under which your project is distributed.setup.py
or pyproject.toml
: A file used for packaging and distributing your project.requirements.txt
or Pipfile
/Pipfile.lock
: A file listing the project's dependencies..gitignore
: A file specifying files and directories that should be ignored by Git.docs/
(Optional): A directory containing documentation for your project.
Example Project Structure
This example demonstrates a typical Python project structure. Let's break down each component:
my_project/
: The root directory for your project.src/my_package/
: This is where your main Python package resides. The __init__.py
file turns the directory into a Python package. module1.py
and module2.py
are example modules within the package.src/main.py
: This could be the entry point of your application, containing the main
function or other top-level logic.tests/
: Contains unit tests for your code. Each module in my_package
should ideally have corresponding tests.README.md
: Provides information about the project.LICENSE
: Specifies the project's licensing.setup.py
: Used to install the package and its dependencies (legacy approach). Modern projects are transitioning to pyproject.toml
.requirements.txt
: Lists the project's dependencies for easy installation using pip install -r requirements.txt
..gitignore
: Specifies files that Git should ignore (e.g., .pyc
files, virtual environment directories).docs/
: Contains project documentation, often built using Sphinx.
my_project/
├── src/
│ ├── my_package/
│ │ ├── __init__.py
│ │ ├── module1.py
│ │ ├── module2.py
│ ├── main.py
├── tests/
│ ├── __init__.py
│ ├── test_module1.py
│ ├── test_module2.py
├── README.md
├── LICENSE
├── setup.py
├── requirements.txt
├── .gitignore
└── docs/
├── index.rst
└── conf.py
The Role of setup.py
The setup.py
file is used to package and distribute your Python project. It defines metadata about your project, such as its name, version, dependencies, and entry points. The example above uses setuptools
, a common packaging tool. find_packages(where='src')
automatically discovers all packages within the src
directory. install_requires
specifies the project's dependencies.
from setuptools import setup, find_packages
setup(
name='my_package',
version='0.1.0',
packages=find_packages(where='src'),
package_dir={'': 'src'},
install_requires=[
'requests',
'numpy',
],
)
pyproject.toml
: A Modern Alternative
This example defines the build system requirements and project metadata. The pyproject.toml
is the modern standard for Python project configuration. It replaces setup.py
and other configuration files. It offers a more declarative and standardized way to manage project metadata, dependencies, and build processes.dependencies
list functions similarly to install_requires
in setup.py
. The [tool.setuptools.packages]
section specifies where to find the packages within the project.
[build-system]
requires = ["setuptools>=61.0", "wheel"]
build-backend = "setuptools.build_meta"
[project]
name = "my_package"
version = "0.1.0"
description = "A short description of my package."
dependencies = [
"requests",
"numpy"
]
[tool.setuptools.packages]
find = {"where" = ["src"]}
Virtual Environments
Using virtual environments is a crucial best practice for managing dependencies in Python projects. A virtual environment creates an isolated environment for your project, preventing conflicts with system-wide packages or dependencies of other projects. The code above demonstrates how to create and activate a virtual environment using the venv
module. After activating the environment, you can install the project's dependencies using pip install -r requirements.txt
.
python3 -m venv .venv
source .venv/bin/activate # On Linux/macOS
.venv\Scripts\activate # On Windows
pip install -r requirements.txt
Best Practices
Here are some best practices for structuring your Python projects:
src/
): Separate your source code from other project files.__init__.py
files minimal: Use them primarily to define package-level imports or version information.flake8
and black
to enforce style guidelines.
Real-Life Use Case Section
Consider a web application built with Flask. The project structure might look like this: In this example, the
my_web_app/
├── src/
│ ├── my_app/
│ │ ├── __init__.py
│ │ ├── models.py
│ │ ├── views.py
│ │ ├── forms.py
│ ├── config.py
│ ├── main.py # Application entry point
├── tests/
│ ├── __init__.py
│ ├── test_models.py
│ ├── test_views.py
├── migrations/
│ └── ... # Database migration files
├── static/
│ └── ... # Static files (CSS, JavaScript, images)
├── templates/
│ └── ... # HTML templates
├── README.md
├── LICENSE
├── setup.py
├── requirements.txt
├── .gitignore
src/my_app
package contains modules related to models, views, and forms. The config.py
file stores application configuration settings. The static
and templates
directories hold static assets and HTML templates, respectively. Database migrations are stored in the migrations
directory. This clear separation of concerns makes the application easier to understand, maintain, and scale.
Interview Tip
When discussing Python project structure in an interview, emphasize the importance of:
requirements.txt
/pyproject.toml
help manage dependencies.tests/
directory.
FAQ
-
Why use a
src/
directory?
Using a
src/
directory separates your source code from other project files, such as documentation, tests, and configuration files. This makes it clearer where the actual code resides and helps prevent naming conflicts. It also simplifies packaging and distribution. -
What's the difference between
requirements.txt
andsetup.py
/pyproject.toml
?
requirements.txt
lists the project's dependencies for installation viapip install -r requirements.txt
.setup.py
(orpyproject.toml
) is used for packaging and distributing the project itself. It includes project metadata (name, version, author) and also specifies dependencies, but its primary purpose is to create a distributable package. -
How do I handle environment-specific configuration?
You can use environment variables or separate configuration files for different environments (development, testing, production). Libraries like
python-dotenv
can help manage environment variables in a development environment. For more complex configurations, consider using a dedicated configuration management library.