Python Projects
The Python project generator can be used to create a modern Python library or application configured with best practices, managed with UV, a single lockfile and virtual environment in an UV workspace, pytest for running tests, and Ruff for static analysis.
Generate a Python Project
Section titled “Generate a Python Project”You can generate a new Python project in two ways:
- Install the Nx Console VSCode Plugin if you haven't already
- Open the Nx Console in VSCode
- Click
Generate (UI)in the "Common Nx Commands" section - Search for
@aws/nx-plugin - py#project - Fill in the required parameters
- Click
Generate
pnpm nx g @aws/nx-plugin:py#projectyarn nx g @aws/nx-plugin:py#projectnpx nx g @aws/nx-plugin:py#projectbunx nx g @aws/nx-plugin:py#projectYou can also perform a dry-run to see what files would be changed
pnpm nx g @aws/nx-plugin:py#project --dry-runyarn nx g @aws/nx-plugin:py#project --dry-runnpx nx g @aws/nx-plugin:py#project --dry-runbunx nx g @aws/nx-plugin:py#project --dry-runOptions
Section titled “Options”| Parameter | Type | Default | Description |
|---|---|---|---|
| name Required | string | - | The name of the Python project |
| directory | string | packages | Parent directory where the project is placed. |
| projectType Required | string | application | Project type |
| moduleName | string | - | Python module name |
Generator Output
Section titled “Generator Output”The generator will create the following project structure in the <directory>/<name> directory:
Directory<module-name>
- __init__.py Module initialisation
- hello.py Example Python source file
Directorytests
- __init__.py Module initialisation
- conftest.py Test configuration
- test_hello.py Example tests
- project.json Project configuration and build targets
- pyproject.toml Packaging configuration file used by UV
- .python-version Contains the project’s Python version
You may also notice the following files created/updated in the root of your workspace:
- pyproject.toml Workspace level packaging configuration for UV
- .python-version Contains the workspace Python version
- uv.lock Lockfile for Python dependencies
Writing Python Source Code
Section titled “Writing Python Source Code”Add your Python source code in the <module-name> directory.
Importing your Library Code in Other Projects
Section titled “Importing your Library Code in Other Projects”Use the add target to add a dependency to a Python project.
Suppose we have created two python projects, my_app and my_lib. These will have fully qualified project names of my_scope.my_app and my_scope.my_lib, and by default will each have module names of my_scope_my_app and my_scope_my_lib.
For my_app to depend on my_lib, we can run the following command:
pnpm nx run my_scope.my_app:add my_scope.my_libyarn nx run my_scope.my_app:add my_scope.my_libnpx nx run my_scope.my_app:add my_scope.my_libbunx nx run my_scope.my_app:add my_scope.my_libYou can then import your library code:
from my_scope_my_lib.hello import say_helloAbove, my_scope_my_lib is the module name for the lib, hello corresponds to the Python source file hello.py, and say_hello is a method defined in hello.py
Dependencies
Section titled “Dependencies”To add dependencies to your project, you can run the add target in your Python project, for example:
pnpm nx run my_scope.my_library:add some-pip-packageyarn nx run my_scope.my_library:add some-pip-packagenpx nx run my_scope.my_library:add some-pip-packagebunx nx run my_scope.my_library:add some-pip-packageThis will add the dependency to your project’s pyproject.toml file, and update the root uv.lock.
Runtime Code
Section titled “Runtime Code”When you use your Python project as runtime code (for example as the handler for an AWS lambda function), you will need to create a bundle of the source code and all its dependencies. You can achieve this by adding a target such as the following to your project.json file:
{ ... "targets": { ... "bundle": { "cache": true, "executor": "nx:run-commands", "outputs": ["{workspaceRoot}/dist/packages/my_library/bundle"], "options": { "commands": [ "uv export --frozen --no-dev --no-editable --project packages/my_library --package my_scope.my_library -o dist/packages/my_library/bundle/requirements.txt", "uv pip install -n --no-deps --no-installer-metadata --no-compile-bytecode --python-platform x86_64-manylinux2014 --python `uv python pin` --target dist/packages/my_library/bundle -r dist/packages/my_library/bundle/requirements.txt" ], "parallel": false }, "dependsOn": ["compile"] }, },}Building
Section titled “Building”Your Python project is configured with a build target (defined in project.json), which you can run via:
pnpm nx run <project-name>:buildyarn nx run <project-name>:buildnpx nx run <project-name>:buildbunx nx run <project-name>:buildWhere <project-name> is the fully qualified name of your project.
The build target will compile, lint and test your project.
Build output can be found in the root dist folder in your workspace, inside a directory for your package and target, for example dist/packages/<my-library>/build
Testing
Section titled “Testing”pytest is configured for testing your project.
Writing Tests
Section titled “Writing Tests”Tests should be written in the test directory within your project, in python files prefixed with test_, for example:
Directorymy_library
- hello.py
Directorytest
- test_hello.py Tests for hello.py
Tests are methods which begin with test_ and make assertions to verify expectations, for example:
from my_library.hello import say_hello
def test_say_hello(): assert say_hello("Darth Vader") == "Hello, Darth Vader!"For more details about how to write tests, please refer to the pytest documentation.
Running Tests
Section titled “Running Tests”Tests will run as part of the build target for your project, but you can also run them separately by running the test target:
pnpm nx run <project-name>:testyarn nx run <project-name>:testnpx nx run <project-name>:testbunx nx run <project-name>:testYou can run an individual test or suite of tests using the -k flag, specifying either the name of the test file or method:
pnpm nx run <project-name>:test -k 'test_say_hello'yarn nx run <project-name>:test -k 'test_say_hello'npx nx run <project-name>:test -k 'test_say_hello'bunx nx run <project-name>:test -k 'test_say_hello'Linting
Section titled “Linting”Python projects use Ruff for linting.
Running the Linter
Section titled “Running the Linter”To invoke the linter to check your project, you can run the lint target.
pnpm nx run <project-name>:lintyarn nx run <project-name>:lintnpx nx run <project-name>:lintbunx nx run <project-name>:lintFixing Lint Issues
Section titled “Fixing Lint Issues”The majority of linting or formatting issues can be fixed automatically. You can tell Ruff to fix lint issues by running with the --configuration=fix argument.
pnpm nx run <project-name>:lint --configuration=fixyarn nx run <project-name>:lint --configuration=fixnpx nx run <project-name>:lint --configuration=fixbunx nx run <project-name>:lint --configuration=fixSimilarly if you would like to fix all lint issues in all packages in your workspace, you can run:
pnpm nx run-many --target lint --all --configuration=fixyarn nx run-many --target lint --all --configuration=fixnpx nx run-many --target lint --all --configuration=fixbunx nx run-many --target lint --all --configuration=fix