0 added
0 removed
Original
2026-01-01
Modified
2026-02-21
1
<p>In this lesson, we'll take a closer look at working with dependencies with Poetry.</p>
1
<p>In this lesson, we'll take a closer look at working with dependencies with Poetry.</p>
2
<h2>Adding and removing dependencies</h2>
2
<h2>Adding and removing dependencies</h2>
3
<p>In the last lesson, we created a project named hello. Let's return to it and add the colorama package - a dependency for hello. It is a popular library that allows you to colorize text in the terminal.</p>
3
<p>In the last lesson, we created a project named hello. Let's return to it and add the colorama package - a dependency for hello. It is a popular library that allows you to colorize text in the terminal.</p>
4
<p>We will add dependencies with the command poetry add NAME:</p>
4
<p>We will add dependencies with the command poetry add NAME:</p>
5
<p>Now we will look at the tool.poetry.dependencies section of the<em>pyproject.toml</em>file. You'll find the following:</p>
5
<p>Now we will look at the tool.poetry.dependencies section of the<em>pyproject.toml</em>file. You'll find the following:</p>
6
<p>As you can see, colorama is installed in the virtual environment and appears in the list of project dependencies. If we want to run a code, we can run the poetry install command and get all the necessary dependencies.</p>
6
<p>As you can see, colorama is installed in the virtual environment and appears in the list of project dependencies. If we want to run a code, we can run the poetry install command and get all the necessary dependencies.</p>
7
<p>Note the text "^0.4.5". It doesn't just mean specifically 0.4.5. The versions from 0.4.5 up to 0.5.0 will be considered compatible. You can also give a specific version, list several permissible versions, or manually specify a range. You can learn more about this variety<a>in the documentation</a>.</p>
7
<p>Note the text "^0.4.5". It doesn't just mean specifically 0.4.5. The versions from 0.4.5 up to 0.5.0 will be considered compatible. You can also give a specific version, list several permissible versions, or manually specify a range. You can learn more about this variety<a>in the documentation</a>.</p>
8
<p>Now let's try to remove the dependencies with the command poetry remove NAME. Python will remove the uninstalled packages from the<em>pyproject.toml</em>file automatically:</p>
8
<p>Now let's try to remove the dependencies with the command poetry remove NAME. Python will remove the uninstalled packages from the<em>pyproject.toml</em>file automatically:</p>
9
<h2>Dependency groups</h2>
9
<h2>Dependency groups</h2>
10
<p>Many tools for developing Python projects are in Python. However, they're usually not needed to run the code. Take, for example, Pytest, a popular framework for writing tests. This package has many dependencies of its own. In a large project, these development tools can take up a lot of space.</p>
10
<p>Many tools for developing Python projects are in Python. However, they're usually not needed to run the code. Take, for example, Pytest, a popular framework for writing tests. This package has many dependencies of its own. In a large project, these development tools can take up a lot of space.</p>
11
<p>The problem is that users do not need all these dependencies because they do not run any tests. However, the user gets all the dependencies with the program and wastes space by having to store them.</p>
11
<p>The problem is that users do not need all these dependencies because they do not run any tests. However, the user gets all the dependencies with the program and wastes space by having to store them.</p>
12
<p>Fortunately, Poetry allows you to describe these packages as a group of dependencies. We will consider all created groups when building the virtual environment, but only the dependencies from the [tool.poetry.dependencies] group will reach the end user.</p>
12
<p>Fortunately, Poetry allows you to describe these packages as a group of dependencies. We will consider all created groups when building the virtual environment, but only the dependencies from the [tool.poetry.dependencies] group will reach the end user.</p>
13
<p>Add the Pytest package to the hello project. We'll put it in the dev group. Dev is the usual name for the development tools and environment. Let's see how it works:</p>
13
<p>Add the Pytest package to the hello project. We'll put it in the dev group. Dev is the usual name for the development tools and environment. Let's see how it works:</p>
14
<p>When you run the command yourself, pay attention to how many packages we will install with the pytest we need. There is a new entry in the<em>pyproject.toml</em>file:</p>
14
<p>When you run the command yourself, pay attention to how many packages we will install with the pytest we need. There is a new entry in the<em>pyproject.toml</em>file:</p>
15
<p>As a result, we can run Pytest. Don't forget to write poetry run pytest instead of pytest. We install the program in a virtual environment and cannot see it from the outside. Let's try running it:</p>
15
<p>As a result, we can run Pytest. Don't forget to write poetry run pytest instead of pytest. We install the program in a virtual environment and cannot see it from the outside. Let's try running it:</p>
16
<p>The poetry run command doesn't just run commands from the virtual environment. It runs any program<em>in the context</em>of the virtual environment. For example, you can use the system program which to find out where the executable file pytest is:</p>
16
<p>The poetry run command doesn't just run commands from the virtual environment. It runs any program<em>in the context</em>of the virtual environment. For example, you can use the system program which to find out where the executable file pytest is:</p>
17
<p>Now let's try to remove the dependency. To do this, you must indicate its group:</p>
17
<p>Now let's try to remove the dependency. To do this, you must indicate its group:</p>
18
<h2>Updating dependencies</h2>
18
<h2>Updating dependencies</h2>
19
<p>To update all dependencies, run the command poetry update. To update a specific dependency, run poetry update NAME. Dependencies will update according to the<a>ranges</a>specified.</p>
19
<p>To update all dependencies, run the command poetry update. To update a specific dependency, run poetry update NAME. Dependencies will update according to the<a>ranges</a>specified.</p>
20
<h2>Lock file</h2>
20
<h2>Lock file</h2>
21
<p>In the previous step, we created each new installation of dependencies and then updated it in the<em>poetry.lock</em>file. Let's discuss this file in more detail. As we already discussed, the file<em>pyproject.toml</em>specifies the dependencies. Each dependency may have its dependencies, which may have their dependencies etc. Dependencies of dependencies are<strong>transitive</strong>dependencies, and they're not always easy to deal with. The dependency system can be very confusing.</p>
21
<p>In the previous step, we created each new installation of dependencies and then updated it in the<em>poetry.lock</em>file. Let's discuss this file in more detail. As we already discussed, the file<em>pyproject.toml</em>specifies the dependencies. Each dependency may have its dependencies, which may have their dependencies etc. Dependencies of dependencies are<strong>transitive</strong>dependencies, and they're not always easy to deal with. The dependency system can be very confusing.</p>
22
<p>There is a term for such a situation -<a>dependency hell</a>. The problem is that we don't capture versions of transitive dependencies in any way. Here's an example:</p>
22
<p>There is a term for such a situation -<a>dependency hell</a>. The problem is that we don't capture versions of transitive dependencies in any way. Here's an example:</p>
23
<ul><li>Our project has a dependent package,<strong>A</strong>, with a fixed version 1.3.2</li>
23
<ul><li>Our project has a dependent package,<strong>A</strong>, with a fixed version 1.3.2</li>
24
<li>Dependency<strong>A</strong>has dependent package<strong>B</strong>with version *</li>
24
<li>Dependency<strong>A</strong>has dependent package<strong>B</strong>with version *</li>
25
</ul><p>In this situation, even without the lock file, the poetry install command would install:</p>
25
</ul><p>In this situation, even without the lock file, the poetry install command would install:</p>
26
<ul><li>For<strong>A</strong>- the specified version</li>
26
<ul><li>For<strong>A</strong>- the specified version</li>
27
<li>For<strong>B</strong>- the latest available version from the repository</li>
27
<li>For<strong>B</strong>- the latest available version from the repository</li>
28
</ul><p>In other words, the choice of version isn't determined. If the author updates<strong>B</strong>and breaks backward compatibility, A will stop working, so the whole project will crash.</p>
28
</ul><p>In other words, the choice of version isn't determined. If the author updates<strong>B</strong>and breaks backward compatibility, A will stop working, so the whole project will crash.</p>
29
<p>You can manually track dependencies of all dependencies and explicitly write their versions in<em>pyproject.toml</em>. But this method may not work because packages are constantly updated and changed. It's also hard to track manually because there are too many dependencies - even a project with five dependencies will have hundreds of transitive dependencies.</p>
29
<p>You can manually track dependencies of all dependencies and explicitly write their versions in<em>pyproject.toml</em>. But this method may not work because packages are constantly updated and changed. It's also hard to track manually because there are too many dependencies - even a project with five dependencies will have hundreds of transitive dependencies.</p>
30
<p>Another option would be to require that the creators of all libraries always specify the version. This option will not work because of the human factor this time.</p>
30
<p>Another option would be to require that the creators of all libraries always specify the version. This option will not work because of the human factor this time.</p>
31
<p>There is one solution that will work, a lock file. It is essentially automated dependency tracking. The contents of a lock file look something like this:</p>
31
<p>There is one solution that will work, a lock file. It is essentially automated dependency tracking. The contents of a lock file look something like this:</p>
32
<p>The first run of the dependency installer will create this file. All installed dependencies are written there, including transitive ones with versions and [hash sums] (<a>https://en.wikipedia.org/wiki/Checksum</a>).</p>
32
<p>The first run of the dependency installer will create this file. All installed dependencies are written there, including transitive ones with versions and [hash sums] (<a>https://en.wikipedia.org/wiki/Checksum</a>).</p>
33
<p>On subsequent runs, the `poetry install' command will always put the data from the lock file. It works even if you delete the<em>.venv</em>folder or add new versions of packages to<em>pyproject.toml</em>. Running it after any amount of time will produce the same result. Now we can say that the project will run for any user at any time.</p>
33
<p>On subsequent runs, the `poetry install' command will always put the data from the lock file. It works even if you delete the<em>.venv</em>folder or add new versions of packages to<em>pyproject.toml</em>. Running it after any amount of time will produce the same result. Now we can say that the project will run for any user at any time.</p>
34
<p>The lock file doesn't affect the behavior of the `update' command for direct dependencies. Let's say the package in our<em>pyproject.toml</em>file has a new version. In this case, Poetry will check if it's possible to update. If so, it will download the new version and automatically update the lock file.</p>
34
<p>The lock file doesn't affect the behavior of the `update' command for direct dependencies. Let's say the package in our<em>pyproject.toml</em>file has a new version. In this case, Poetry will check if it's possible to update. If so, it will download the new version and automatically update the lock file.</p>
35
<p>If we don't want to install packages, we can use the poetry update --lock command. It will check which the new versions match the versions specified in the configuration and only update the lock file.</p>
35
<p>If we don't want to install packages, we can use the poetry update --lock command. It will check which the new versions match the versions specified in the configuration and only update the lock file.</p>