Skip to content

Manage Project#

Choose a Python interpreter#

If you have used pdm init, you must have already seen how PDM detects and selects the Python interpreter. After initialized, you can also change the settings by pdm use <python_version_or_path>. The argument can be either a version specifier of any length, or a relative or absolute path to the python interpreter, but remember the Python interpreter must conform with the requires-python constraint in the project file.

Application or Library

You may have noticed that PDM will ask you whether the project is a library to be uploaded to PyPI. Here is an good explanation of the difference between them. PDM knows that by inspecting the field in pyproject.toml. If it is not empty, it will be considered as a library. A library can be built by pdm build or other PEP 517 builders, and itself will be installed in editable mode every time you execute pdm sync or pdm install, unless opted out with --no-self option. On the contrary, an application isn't installable because it's missing the project name.

How requires-python controls the project#

PDM respects the value of requires-python in the way that it tries to pick package candidates that can work on all python versions that requires-python contains. For example, if requires-python is >=2.7, PDM will try to find the latest version of foo, whose requires-python version range is a superset of >=2.7.

So, make sure you write requires-python properly if you don't want any outdated packages to be locked.

Working with Python < 3.7#

Although PDM run on Python 3.7 and above, you can still have lower Python versions for your working project. But remember, if your project is a library, which needs to be built, published or installed, you make sure the PEP 517 build backend being used supports the lowest Python version you need. For instance, the default backend pdm-pep517 only works on Python 3.7+, so if you run pdm build on a project with Python 3.6, you will get an error. Most modern build backends have dropped the support for Python 3.6 and lower, so it is highly recommended to upgrade the Python version to 3.7+. Here are the supported Python range for some commonly used build backends, we only list those that support PEP 621 since otherwise PDM can't work with them.

Backend Supported Python Support PEP 621
pdm-pep517 >=3.7 Yes
setuptools>=60 >=3.7 Experimental
hatchling >=3.7 Yes
flit-core>=3.4 >=3.6 Yes
flit-core>=3.2,<3.4 >=3.4 Yes

Note that if your project is an application(without name metadata), the above limitation of backends don't apply, since you don't need a build backend after all, and you can use a Python version up to 2.7.

Build distribution artifacts#

$ pdm build
- Building sdist...
- Built pdm-test-0.0.0.tar.gz
- Building wheel...
- Built pdm_test-0.0.0-py3-none-any.whl

The artifacts will be available at dist/ and able to upload to PyPI.

Configure the project#

PDM's config command works just like git config, except that --list isn't needed to show configurations.

Show the current configurations:

pdm config

Get one single configuration:

pdm config pypi.url

Change a configuration value and store in home configuration:

pdm config pypi.url ""

By default, the configuration are changed globally, if you want to make the config seen by this project only, add a --local flag:

pdm config --local pypi.url ""

Any local configurations will be stored in .pdm.toml under the project root directory.

The configuration files are searched in the following order:

  1. <PROJECT_ROOT>/.pdm.toml - The project configuration
  2. <CONFIG_ROOT>/config.toml - The home configuration
  3. <SITE_CONFIG_ROOT>/config.toml - The site configuration

where <CONFIG_ROOT> is:


If -g/--global option is used, the first item will be replaced by <CONFIG_ROOT>/global-project/.pdm.toml.

You can find all available configuration items in Configuration Page.

Configure PyPI indexes#

From 2.4.0, PDM supports multiple PyPI indexes in the configuration file. To add a new index, include the following in the configuration file:

url = ""
verify_ssl = false

The available options are:

  • url: The URL of the index
  • verify_ssl: (Optional)Whether to verify SSL certificates, default to true
  • username: (Optional)The username for the index
  • password: (Optional)The password for the index
  • type: (Optional) index or find_links, default to index

To configure the main index, omit the name of the index:

url = ""
verify_ssl = true

The index config can be also retrieved or updated via pdm config command:

# Get the url of the index named "extra"
pdm config pypi.extra.url
# Set the username and password of the index named "extra"
pdm config pypi.extra.username "foo"
pdm config pypi.extra.password "password4foo"


Configured indexes will be tried after the sources in pyproject.toml, if you want to completely ignore the locally configured indexes, including the main index, set the config value pypi.ignore_stored_index to False and only the sources in pyproject.toml will be honored.

Publish the project to PyPI#

With PDM, you can build and then upload your project to PyPI in one step.

pdm publish

You can specify which repository you would like to publish:

pdm publish -r pypi

PDM will look for the repository named pypi from the configuration and use the URL for upload. You can also give the URL directly with -r/--repository option:

pdm publish -r

See all supported options by typing pdm publish --help.

Configure the repository secrets for upload#

When using the pdm publish command, it reads the repository secrets from the global config file(<CONFIG_ROOT>/config.toml). The content of the config is as follows:

username = "frostming"
password = "<secret>"

url = ""
username = "frostming"
password = "<secret>"
ca_certs = "/path/to/custom-cacerts.pem"

A PEM-encoded Certificate Authority bundle (ca_certs) can be used for local / custom PyPI repositories where the server certificate is not signed by the standard certifi CA bundle.


Repositories are different from indexes in the previous section. Repositories are for publishing while indexes are for locking and resolving. They don't share the configuration.


You don't need to configure the url for pypi and testpypi repositories, they are filled by default values. The username, password, and certificate authority bundle can be passed in from the command line for pdm publish via --username, --password, and --ca-certs, respectively.

To change the repository config from the command line, use the pdm config command:

pdm config repository.pypi.username "__token__"
pdm config repository.pypi.password "my-pypi-token"

pdm config ""
pdm config "/path/to/custom-cacerts.pem"

Cache the installation of wheels#

If a package is required by many projects on the system, each project has to keep its own copy. This may become a waste of disk space especially for data science and machine learning libraries.

PDM supports caching the installations of the same wheel by installing it into a centralized package repository and linking to that installation in different projects. To enabled it, run:

pdm config install.cache on

It can be enabled on a project basis, by adding --local option to the command.

The caches are located under $(pdm config cache_dir)/packages. One can view the cache usage by pdm cache info. But be noted the cached installations are managed automatically -- They get deleted when not linked from any projects. Manually deleting the caches from the disk may break some projects on the system.


Only the installation of named requirements resolved from PyPI can be cached.

Show the current Python environment#

$ pdm info
PDM version:
Python Interpreter:
  /opt/homebrew/opt/python@3.9/bin/python3.9 (3.9)
Project Root:
Project Packages:

# Show environment info
$ pdm info --env
  "implementation_name": "cpython",
  "implementation_version": "3.8.0",
  "os_name": "nt",
  "platform_machine": "AMD64",
  "platform_release": "10",
  "platform_system": "Windows",
  "platform_version": "10.0.18362",
  "python_full_version": "3.8.0",
  "platform_python_implementaiton": "CPython",
  "python_version": "3.8",
  "sys_platform": "win32"

This command is useful for checking which mode is being used by the project:

Manage global project#

Sometimes users may want to keep track of the dependencies of global Python interpreter as well. It is easy to do so with PDM, via -g/--global option which is supported by most subcommands.

If the option is passed, <CONFIG_ROOT>/global-project will be used as the project directory, which is almost the same as normal project except that pyproject.toml will be created automatically for you and it doesn't support build features. The idea is taken from Haskell's stack.

However, unlike stack, by default, PDM won't use global project automatically if a local project is not found. Users should pass -g/--global explicitly to activate it, since it is not very pleasing if packages go to a wrong place. But PDM also leave the decision to users, just set the config global_project.fallback to true.

By default, when pdm uses global project implicitly the following message is printed: Project is not found, fallback to the global project. To disable this message set the config global_project.fallback_verbose to false.

If you want global project to track another project file other than <CONFIG_ROOT>/global-project, you can provide the project path via -p/--project <path> option.


Be careful with remove and sync --clean/--pure commands when global project is used, because it may remove packages installed in your system Python.

Import project metadata from existing project files#

If you are already using other package manager tools like Pipenv or Poetry, it is easy to migrate to PDM. PDM provides import command so that you don't have to initialize the project manually, it now supports:

  1. Pipenv's Pipfile
  2. Poetry's section in pyproject.toml
  3. Flit's section in pyproject.toml
  4. requirements.txt format used by pip
  5. setuptools requires setuptools to be installed in the project environment. You can do this by configuring venv.with_pip to true for venv and pdm add setuptools for __pypackages__)

Also, when you are executing pdm init or pdm install, PDM can auto-detect possible files to import if your PDM project has not been initialized yet.


Converting a will execute the file with the project interpreter. Make sure setuptools is installed with the interpreter and the is trusted.

Export locked packages to alternative formats#

You can also export pdm lock to other formats, to ease the CI flow or image building process. Currently, only requirements.txt format is supported:

pdm export -o requirements.txt


You can also run pdm export with a .pre-commit hook.

Working with version control#

You must commit the pyproject.toml file. You should commit the pdm.lock file. Do not commit the .pdm.toml file.

The pyproject.toml file must be committed as it contains the project's build metadata and dependencies needed for PDM. It is also commonly used by other python tools for configuration. Read more about the pyproject.toml file at

You should be committing the pdm.lock file, by doing so you ensure that all installers are using the same versions of dependencies. To learn how to update dependencies see update existing dependencies.

It is not necessary to commit your .pdm.toml file as it contains configuration specific to your system. If you are using git you can safely add .pdm.toml to your .gitignore file.

Hide the credentials from pyproject.toml#

There are many times when we need to use sensitive information, such as login credentials for the PyPI server and username passwords for VCS repositories. We do not want to expose this information in pyproject.toml and upload it to git.

PDM provides several methods to achieve this:

  1. User can give the auth information with environment variables which are encoded in the URL directly:
url = "http://${INDEX_USER}:${INDEX_PASSWD}"
name = "test"
verify_ssl = false

dependencies = [
  "mypackage @ git+http://${VCS_USER}:${VCS_PASSWD}"

Environment variables must be encoded in the form ${ENV_NAME}, other forms are not supported. Besides, only auth part will be expanded.

  1. If the credentials are not provided in the URL and a 401 response is received from the server, PDM will prompt for username and password when -v/--verbose is passed as command line argument, otherwise PDM will fail with an error telling users what happens. Users can then choose to store the credentials in the keyring after a confirmation question.

  2. A VCS repository applies the first method only, and an index server applies both methods.

Manage caches#

PDM provides a convenient command group to manage the cache, there are five different caches:

  1. wheels/ stores the built results of non-wheel distributions and files.
  2. http/ stores the HTTP response content.
  3. metadata/ stores package metadata retrieved by the resolver.
  4. hashes/ stores the file hashes fetched from the package index or calculated locally.
  5. packages/ The centralized repository for installed wheels.

See the current cache usage by typing pdm cache info. Besides, you can use add, remove and list subcommands to manage the cache content. Find the usage by the --help option of each command.