# Install Python package from plugin

**URL:** <https://platform.jetbrains.com/t/install-python-package-from-plugin/3839>\
**Category:** IntelliJ Platform\
**Tags:** api, pycharm, plugin-development\
**Created:** [March 9, 2026, 11:23pm UTC](https://platform.jetbrains.com/t/install-python-package-from-plugin/3839 "2026-03-09T23:23:24Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![peppar](https://sea1.discourse-cdn.com/flex001/user_avatar/platform.jetbrains.com/peppar/32/1294_2.png) [@peppar](https://platform.jetbrains.com/u/peppar)\
**Post date:** [March 9, 2026, 11:23pm UTC](https://platform.jetbrains.com/t/install-python-package-from-plugin/3839/1 "2026-03-09T23:23:24Z")

</div>

I’d like for my plugin to install a certain Python package, but I only find internal API’s that achieve this. Is there any non-internal API that could be used to check for if a certain package exists, and if not, install it?

The package provides a testing framework for the language I’m adding support for. I can’t embed the testing framework with the plugin.

---

<div class="post-metadata">

**Author:** ![Lukas\_Kremla](https://avatars.discourse-cdn.com/v4/letter/l/41988e/32.png) [@Lukas\_Kremla](https://platform.jetbrains.com/u/Lukas_Kremla)\
**Post date:** [March 10, 2026, 8:39am UTC](https://platform.jetbrains.com/t/install-python-package-from-plugin/3839/2 "2026-03-10T08:39:02Z")

</div>

This is a bit fragmented right now - PyPackageManager is deprecated, but might still be available - that’s the old thing that worked. They did add new API, but I had to abandon that because it was incomplete/part internal.

What I had to resort to was getting the user’s python interpreter, finding its path, and then running manual pip commands to check if a package is present and handle installation if needed as a subprocess.

I later abandoned python packages altogether and found a way to achieve what the python package did with bundled binaries - I get that this might not be possible for your use case, but make sure there is no such viable workaround that could work for you. Having deps bundled is easier and provides a smoother workflow.

---

<div class="post-metadata">

**Author:** ![peppar](https://sea1.discourse-cdn.com/flex001/user_avatar/platform.jetbrains.com/peppar/32/1294_2.png) [@peppar](https://platform.jetbrains.com/u/peppar)\
**Post date:** [March 10, 2026, 1:11pm UTC](https://platform.jetbrains.com/t/install-python-package-from-plugin/3839/4 "2026-03-10T13:11:44Z")

</div>

Thank you Lukas, I might have to manually run pip commands if there is no stable API to consume.

I don’t want to embed the resource for a mix of reasons including licensing, and that users can tie into a specific version of the package.

---

<div class="post-metadata">

**Author:** ![chbndrhnns](https://sea1.discourse-cdn.com/flex001/user_avatar/platform.jetbrains.com/chbndrhnns/32/179_2.png) [@chbndrhnns](https://platform.jetbrains.com/u/chbndrhnns)\
**Post date:** [March 11, 2026, 7:56am UTC](https://platform.jetbrains.com/t/install-python-package-from-plugin/3839/5 "2026-03-11T07:56:02Z")

</div>

Recently, part of the interface of `PythonPackageManager` got promoted to `ApiStatus.Experimental` status.

> <https://github.com/JetBrains/intellij-community/commit/75776cd777ae069057da660ba4ab0c154bdbd727>
>
> Promote five methods from @ApiStatus.Internal to @ApiStatus.Experimental:
> \- list…InstalledPackages()
> \- listInstalledPackagesSnapshot()
> \- listOutdatedPackages()
> \- listOutdatedPackagesSnapshot()
> \- extractDependenciesCached()
> 
> Update pycharm\_api.txt allowlist accordingly.
> 
> GitOrigin-RevId: 00c31c76a17ea38919886f586734c0947187c522

Sadly, installing a package was not part of it.

---

<div class="post-metadata">

**Author:** ![vitaly.legchilkin](https://sea1.discourse-cdn.com/flex001/user_avatar/platform.jetbrains.com/vitaly.legchilkin/32/2687_2.png) [@vitaly.legchilkin](https://platform.jetbrains.com/u/vitaly.legchilkin)\
**Post date:** [March 11, 2026, 8:51am UTC](https://platform.jetbrains.com/t/install-python-package-from-plugin/3839/6 "2026-03-11T08:51:16Z")

</div>

@peppar I think we could open `PythonPackageManagerUI.installPackagesWithModalProgressBlocking` or `PythonPackageManager.install` as **Experimental** , but there is no guarantee that it will not be changed in 2026.2 or later.

> **[Make PythonPackageManagerUI install methods Experimental API : PY-88392](https://youtrack.jetbrains.com/issue/PY-88392)**
>
> Description Promote install-related methods in "PythonPackageManagerUI" from "@ApiStatus.Internal" to "@ApiStatus.Experimental" to make them available as public (experimental) API for plugin developers....

---

<div class="post-metadata">

**Author:** ![szabope](https://sea1.discourse-cdn.com/flex001/user_avatar/platform.jetbrains.com/szabope/32/1466_2.png) [@szabope](https://platform.jetbrains.com/u/szabope)\
**Post date:** [March 24, 2026, 8:43am UTC](https://platform.jetbrains.com/t/install-python-package-from-plugin/3839/8 "2026-03-24T08:43:39Z")

</div>

These methods unfortunately don’t accept a version specification for the package. For this, I can revert to using `PyPackageManagerUI`.

However, I also need a way to determine whether the package is currently installed so that I can disable the button when it isn’t needed. What would be the ideal way to do that?

PyPackageManager used to support that, but it is now marked “deprecated, for removal”.

---

<div class="post-metadata">

**Author:** ![vitaly.legchilkin](https://sea1.discourse-cdn.com/flex001/user_avatar/platform.jetbrains.com/vitaly.legchilkin/32/2687_2.png) [@vitaly.legchilkin](https://platform.jetbrains.com/u/vitaly.legchilkin)\
**Post date:** [March 24, 2026, 9:22am UTC](https://platform.jetbrains.com/t/install-python-package-from-plugin/3839/9 "2026-03-24T09:22:18Z")

</div>

> [@szabope](#):
>
> PyPackageManagerUI

This class might also be deprecated, but for now I think it’s the only public way.

We have some public methods in `PythonPackageManager` exposed as experimental, you can use them.

---

<div class="post-metadata">

**Author:** ![szabope](https://sea1.discourse-cdn.com/flex001/user_avatar/platform.jetbrains.com/szabope/32/1466_2.png) [@szabope](https://platform.jetbrains.com/u/szabope)\
**Post date:** [March 28, 2026, 4:01pm UTC](https://platform.jetbrains.com/t/install-python-package-from-plugin/3839/10 "2026-03-28T16:01:11Z")

</div>

Hi Vitaly,

Huge thanks, with that help I was able to make my plugins compatible with PyCharm 261.

Edit: got it working so the following I don’t need anymore.

> However, I also support Idea, and verification fails for PythonPackage.getName() and .getVersion()  
> PythonPackage is @Internal on idea/261.22158.277, but public on PyCharm 261.22158.220  
> Do you think it was possible to remove the annotation in Idea, too?
