# Advanced Usage
- [Using the python-version input](advanced-usage.md#using-the-python-version-input)
- [Specifying a Python version](advanced-usage.md#specifying-a-python-version)
- [Specifying a PyPy version](advanced-usage.md#specifying-a-pypy-version)
- [Specifying multiple Python/PyPy versions](advanced-usage.md#specifying-multiple-pythonpypy-versions)
- [Matrix Testing](advanced-usage.md#matrix-testing)
- [Using the python-version-file input](advanced-usage.md#using-the-python-version-file-input)
- [Check latest version](advanced-usage.md#check-latest-version)
- [Caching packages](advanced-usage.md#caching-packages)
- [Outputs and environment variables](advanced-usage.md#outputs-and-environment-variables)
- [Outputs](advanced-usage.md#outputs)
- [Environment variables](advanced-usage.md#environment-variables)
- [Using update-environment flag](advanced-usage.md#using-update-environment-flag)
- [Available versions of Python and PyPy](advanced-usage.md#available-versions-of-python-pypy-and-graalpy)
- [Python](advanced-usage.md#python)
- [PyPy](advanced-usage.md#pypy)
- [GraalPy](advanced-usage.md#graalpy)
- [Hosted tool cache](advanced-usage.md#hosted-tool-cache)
- [Using `setup-python` with a self-hosted runner](advanced-usage.md#using-setup-python-with-a-self-hosted-runner)
- [Windows](advanced-usage.md#windows)
- [Linux](advanced-usage.md#linux)
- [macOS](advanced-usage.md#macos)
- [Using `setup-python` on GHES](advanced-usage.md#using-setup-python-on-ghes)
- [Allow pre-releases](advanced-usage.md#allow-pre-releases)
## Using the `python-version` input
### Specifying a Python version
If there is a specific version of Python that you need and you don't want to worry about any potential breaking changes due to patch updates (going from `3.7.5` to `3.7.6` for example), you should specify the **exact major, minor, and patch version** (such as `3.7.5`):
```yaml
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.7.5'
- run: python my_script.py
```
- The only downside to this is that setup may take a little longer. If the exact version is not already installed on the runner due to more recent versions, the exact version will have to be downloaded.
- MSI installers are used on Windows for this, so runs will take a little longer to set up vs macOS and Linux.
You can specify **only a major and minor version** if you are okay with the most recent patch version being used:
```yaml
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.7'
- run: python my_script.py
```
- There will be a single patch version already installed on each runner for every minor version of Python that is supported.
- The patch version that will be preinstalled, will generally be the latest and every time there is a new patch released, the older version that is preinstalled will be replaced.
- Using the most recent patch version will result in a very quick setup since no downloads will be required since a locally installed version of Python on the runner will be used.
You can specify the version with **prerelease tag** to download and set up an accurate pre-release version of Python:
```yaml
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.12.0-alpha.1'
- run: python my_script.py
```
It's also possible to use **x.y-dev syntax** to download and set up the latest patch version of Python, alpha, beta and rc (release candidate) releases included. (for specified major & minor versions):
```yaml
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.12-dev'
- run: python my_script.py
```
You can also use several types of ranges that are specified in [semver](https://github.com/npm/node-semver#ranges), for instance:
- **[ranges](https://github.com/npm/node-semver#ranges)** to download and set up the latest available version of Python satisfying a range:
```yaml
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '>=3.9 If your runner is configured as a service and you run into problems, make sure the user that the service is running as is correct. For more information, you can [check the status of your self-hosted runner](https://docs.github.com/en/actions/hosting-your-own-runners/configuring-the-self-hosted-runner-application-as-a-service#checking-the-status-of-the-service).
## Using `setup-python` on GHES
### Avoiding rate limit issues
`setup-python` comes pre-installed on the appliance with GHES if Actions is enabled. When dynamically downloading Python distributions, `setup-python` downloads distributions from [`actions/python-versions`](https://github.com/actions/python-versions) on github.com (outside of the appliance). These calls to `actions/python-versions` are by default made via unauthenticated requests, which are limited to [60 requests per hour per IP](https://docs.github.com/en/rest/overview/resources-in-the-rest-api#rate-limiting). If more requests are made within the time frame, then the action leverages the `raw API` to retrieve the version-manifest. This approach does not impose a rate limit and hence facilitates unrestricted consumption. This is particularly beneficial for GHES runners, which often share the same IP due to Network Address Translation (NAT), to avoid the quick exhaustion of the unauthenticated rate limit.
### No access to github.com
If the runner is not able to access github.com, any Python versions requested during a workflow run must come from the runner's tool cache. See "[Setting up the tool cache on self-hosted runners without internet access](https://docs.github.com/en/enterprise-server/admin/github-actions/managing-access-to-actions-from-githubcom/setting-up-the-tool-cache-on-self-hosted-runners-without-internet-access)" for more information.
## Allow pre-releases
The `allow-prereleases` flag defaults to `false`.
If `allow-prereleases` is set to `true`, the action will allow falling back to pre-release versions of Python when a matching GA version of Python is not available.
This allows for example to simplify reuse of `python-version` as an input of nox for pre-releases of Python by not requiring manipulation of the `3.y-dev` specifier.
For CPython, `allow-prereleases` will only have effect for `x.y` version range (e.g. `3.12`).
Let's say that python 3.12 is not generally available, the following workflow will fallback to the most recent pre-release of python 3.12:
```yaml
jobs:
test:
name: ${{ matrix.os }} / ${{ matrix.python_version }}
runs-on: ${{ matrix.os }}-latest
strategy:
fail-fast: false
matrix:
os: [Ubuntu, Windows, macOS]
python_version: ["3.11", "3.12"]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "${{ matrix.python_version }}"
allow-prereleases: true
- run: pipx run nox --error-on-missing-interpreters -s tests-${{ matrix.python_version }}
```