373

I need to install a package from PyPi straight within my script. Maybe there's some module or distutils (distribute, pip etc.) feature which allows me to just execute something like pypi.install('requests') and requests will be installed into my virtualenv.

chuwy
  • 5,158
  • 4
  • 17
  • 22
  • 4
    Why don't you define the related module as dependency in the setup.py of your own package? – Andreas Jung Sep 08 '12 at 17:34
  • 6
    you know ... the way its actually supposed to be done ... but you could always os.system("pip install blah") but you may need sudo access ... better to just make it a dependency in your setup.py – Joran Beasley Sep 08 '12 at 17:35
  • 2
    Would you consider changing the accepted answer here? Importing `pip` is never a good idea - the mere fact that all of its contents are in `_internal` starting from version 10... – Antti Haapala Dec 06 '19 at 21:53
  • Not related, but some complications that might occur: https://stackoverflow.com/questions/56974185/import-runtime-installed-module-using-pip-in-python-3. – CristiFati Dec 09 '19 at 12:15
  • @AnttiHaapala I certainly can change it, but I still don't see a better solution. – chuwy Dec 11 '19 at 09:19
  • 2
    @chuwy https://stackoverflow.com/a/50255019/918959 <= this one. `pip._internal` is not designed to be importable, it can do absolutely random things when imported in another program. – Antti Haapala Dec 11 '19 at 10:26
  • 2
    @Antti is right. Currently [the best answer is here](https://stackoverflow.com/a/50255019/11138259). The current accepted answer is not recommended and prone to break, as is clearly stated in [_pip_'s user guide's section on "Using pip from your program"](https://pip.pypa.io/en/latest/user_guide/#using-pip-from-your-program). Coincidentally this is [being discussed by _pip_'s maintainers currently as well](https://discuss.python.org/t/can-we-finally-add-a-minimal-api-to-pip/2833). – sinoroc Dec 12 '19 at 13:58
  • 3
    @AnttiHaapala okay I changed it. I personally don't like both solutions, but I'm far away from Python these days, so I trust your opinion. – chuwy Dec 13 '19 at 17:12
  • 1
    @chuwy thanks. I do not like the fact that `pip` cannot be imported much either, am hoping there would be a better solution, but this `sys.executable` is the most portable way to do it. – Antti Haapala Dec 13 '19 at 18:19
  • 1
    @chuwy Thanks for changing the accepted answer! From someone who was steered in the right direction because you did so. – David Z May 24 '20 at 07:08

9 Answers9

399

You can also use something like:

import pip

def install(package):
    if hasattr(pip, 'main'):
        pip.main(['install', package])
    else:
        pip._internal.main(['install', package])

# Example
if __name__ == '__main__':
    install('argh')
Tomasz Gandor
  • 5,982
  • 2
  • 45
  • 46
Rikard Anglerud
  • 4,281
  • 2
  • 14
  • 3
  • Here this exits after installing. – fiatjaf Oct 30 '13 at 20:37
  • @Rikard Anglerud. Is there an option to upgrade the packages in a batch? something like `'install --upgrade'`? – jason Sep 16 '14 at 06:39
  • @RikAng What to change in your code if i want to install multiple packages – Patrick Oct 13 '14 at 06:25
  • Is there a way to pass options when installing, for example the version of the package? If yes, could you please add it to your answer just for completeness. – nbro Jun 03 '15 at 22:19
  • 3
    @nbro you pass options to `pip.main()` as you would on the command line (but with each option as a separate entry in the list, instead of a single string). And to specify which version of the package you want, do the same as on the command line.. ex: `pip.main(['install', 'pip==7.1.0'])` – Kaos Jul 20 '15 at 10:18
  • 3
    See also http://stackoverflow.com/questions/6457794/pip-install-r-continue-past-installs-that-fail, which shows how to handle the case where an install fails. – Myer Jul 20 '15 at 11:21
  • 2
    This is also a great option for installing new python libraries on Windows via the Python console if you don't have a machine with powershell on it. – Jared Nov 28 '15 at 14:26
  • How can I have this working for a particular virtualenv? I'm trying to automate generating wheels for a matrix of packages and python versions. What I want is to create a virtualenv, install some dependencies, and create the wheel. – Xabs Mar 22 '16 at 16:48
  • Replying to myself: to install in a specific virtualenv: `pip install --target=my-virtualenv/lib/python2.7/site-packages`. – Xabs Mar 22 '16 at 17:00
  • 1
    I'm getting `ValueError: Unable to configure handler 'console': 'OutStream' object has no attribute 'closed'` when using this function. Anyone know why ? – kaycee Apr 11 '16 at 19:56
  • 3
    Doesn't work and gave me the error: Traceback (most recent call last): File "/home/***/git/pip.py", line 9, in install('arg') File "/home/***/git/pip.py", line 4, in install pip.main(['install', package]) AttributeError: 'module' object has no attribute 'main' – tribbloid Sep 04 '16 at 07:52
  • 1
    How do you do this with pip3? – pitchblack408 May 24 '17 at 22:33
  • 26
    `from pip._internal import main as pipmain` then you can use `pipmain()` just like the deprecated `pip.main()` see https://stackoverflow.com/questions/43398961/pip-module-has-no-attribute-main – 3pitt May 30 '18 at 15:48
  • For some reason, after compiling and installing a local version of python 2.7.15, the command-line pip was not working (it tried to import stuff from the system-installed python and complained about missing pip distribution). The above solution worked for me, but after upgrading pip (`pip.main(["install", "--upgrade", "pip"])`), I had to use the modification suggested by @MikePalmice to further install packages. – bli May 31 '18 at 08:52
  • how do you use a requirements file and install packages to a different directory? – red888 Jun 14 '18 at 22:54
  • 19
    its depreceated now. – Morse Jul 08 '18 at 01:12
  • May not work with virtualenv https://github.com/explosion/spaCy/commit/1754e0db9b9974ce76d935bc1422df8a370265ab – Kelvin Ng Jul 11 '19 at 20:34
  • 10
    It's deprecated for a reason & not recommended anymore. see https://pip.pypa.io/en/latest/user_guide/#using-pip-from-your-program – N.B.K Jul 28 '19 at 16:56
  • This fails with `AttributeError: module 'pip' has no attribute '_internal'`. However, it does work if you `import pip._internal` – cowlinator Aug 21 '19 at 19:47
  • 1
    This works for me on Python 3.6.7: `import pip._internal.main ; pip._internal.main.main(['install', 'MODULENAMEHERE'])`. – Basj Nov 12 '19 at 12:23
  • 2
    Does not work, update please. https://pip.pypa.io/en/latest/user_guide/#using-pip-from-your-program – wim Dec 05 '19 at 16:09
  • 3
    the official python docs explicitly recommend AGAINST doing such a thing. Whyever was this upvoted? – dotbit Dec 11 '19 at 07:35
  • 1
    Because in specific cases (e.g. when your cannot update your PATH on a corporate network) this is the only way to install a module. Generally, it is hard to take the docs seriously when it recommends "against something" without providing an alternative solution. – Borislav Aymaliev Apr 27 '20 at 09:30
366

The officially recommended way to install packages from a script is by calling pip's command-line interface via a subprocess. Most other answers presented here are not supported by pip. Furthermore since pip v10, all code has been moved to pip._internal precisely in order to make it clear to users that programmatic use of pip is not allowed.

Use sys.executable to ensure that you will call the same pip associated with the current runtime.

import subprocess
import sys

def install(package):
    subprocess.check_call([sys.executable, "-m", "pip", "install", package])
wim
  • 266,989
  • 79
  • 484
  • 630
Aaron de Windt
  • 13,661
  • 12
  • 44
  • 58
  • 2
    One issue with this is that, for novice users on Windows, python and pip are not always on their PATH, and so a .py file that could be double-clicked would be quite convenient, whereas a "pip install xxx" comment can be quite tricky. – jdpipe Apr 17 '20 at 01:27
  • 6
    CalledProcessError: Command '['C:\\ProgramData\\Anaconda3\\pythonw.exe', '-m', 'pip', 'install', 'googleapiclient']' returned non-zero exit status 1. – parvij May 13 '20 at 18:30
  • I'm trying to use this approach, but my python is embedded/started from another executable, so "sys.executable" doesn't return the right path. Is there an alternative that would work for python that's started by some other process? – user441669 Dec 26 '20 at 23:56
  • @user441669 Can you give my a bit more information about your setup? Something I can use to recreate your problem. – Aaron de Windt Dec 27 '20 at 00:22
81

If you want to use pip to install required package and import it after installation, you can use this code:

def install_and_import(package):
    import importlib
    try:
        importlib.import_module(package)
    except ImportError:
        import pip
        pip.main(['install', package])
    finally:
        globals()[package] = importlib.import_module(package)


install_and_import('transliterate')

If you installed a package as a user you can encounter the problem that you cannot just import the package. See How to refresh sys.path? for additional information.

Community
  • 1
  • 1
rominf
  • 2,123
  • 2
  • 18
  • 31
  • 4
    Any idea how to do that on Python 3? `imp.reload(site)` gets me `RuntimeError: dictionary changed size during iteration` – kgadek Aug 03 '15 at 16:35
  • where does this install the package, after i did this, i was not able to do `pip uninstall `. I can still uninstall it using `pip.main` but just wanted to know where does it install the package? – Ishan Khare Apr 26 '16 at 12:20
  • Was curious. would this work properly if i do: `pip install requests[security]` ? I wasnt sure if it would properly define the globals correctly. – Fallenreaper May 08 '17 at 16:47
  • 4
    Outdated. `pip.main` no longer works. https://pip.pypa.io/en/latest/user_guide/#using-pip-from-your-program – wim Dec 05 '19 at 16:10
  • Does importing within a function really import into the main namespace, or just the namespace of that `install_and_import` function? – sh37211 Mar 31 '21 at 00:26
24

This should work:

import subprocess

def install(name):
    subprocess.call(['pip', 'install', name])
quantum
  • 3,292
  • 25
  • 48
  • 1
    Yes it's definitely should work. But I thought there is more elegant way;) I'll be waiting a little bit, may be there is. – chuwy Sep 08 '12 at 18:03
  • 1
    @Downvoter: What exactly is wrong with my answer? This answer has all the OP wanted. It doesn't even use a shell. – quantum Sep 08 '12 at 18:09
  • 13
    It depends on the right version of pip being first on the path. If the user is running an alternate python installation, pip will install into the first one instead of the current one. The import approach above will install in the right place. I upvoted anyway to counter the down vote. – GaryBishop Jan 17 '14 at 11:57
  • Windows even don't have pip on PATH by default. – Smit Johnth Aug 07 '15 at 03:46
  • 6
    Depending on how the script is running you wont call the right pip. – Natim Jan 13 '16 at 13:13
  • 1
    There is a lot of situations when this approach will not work. e.g. when you use several versions of python on one machine and you interpret current script with not default python. – running.t Jan 10 '17 at 14:38
  • 1
    Apparently, this approach is preferred by the pip team at this time. – uchuugaka Aug 27 '17 at 16:58
  • Sadly, this works well with virtualenv https://github.com/explosion/spaCy/commit/1754e0db9b9974ce76d935bc1422df8a370265ab – Kelvin Ng Apr 16 '18 at 10:46
  • "Sadly, this works well with..." @KelvinNg did you mean to say it doesn't work well with virtualenv? – Jordan Mackie Jul 10 '19 at 15:58
  • 1
    @JordanMackie No, I just feel sad call `pip` programatically doesn't work but this one does. – Kelvin Ng Jul 11 '19 at 20:36
  • 6
    Calling `[sys.executable, '-m', 'pip', 'install', name]` is making sure to get the "right" pip here. – wim Dec 05 '19 at 16:11
23

i added some exception handling to @Aaron's answer.

import subprocess
import sys

try:
    import pandas as pd
except ImportError:
    subprocess.check_call([sys.executable, "-m", "pip", "install", 'pandas'])
finally:
    import pandas as pd
Sohan Das
  • 1,231
  • 2
  • 9
  • 15
5

You define the dependent module inside the setup.py of your own package with the "install_requires" option.

If your package needs to have some console script generated then you can use the "console_scripts" entry point in order to generate a wrapper script that will be placed within the 'bin' folder (e.g. of your virtualenv environment).

Andreas Jung
  • 1
  • 18
  • 70
  • 118
  • 1
    This is the correct answer and the only sensible way to manage a Python projects' dependencies. It will work with virtualenv, Fabric, buildout, you name it. The method described by @xiaomao, even though answering exactly what the OP asked, is pure madness. – Lukas Graf Sep 08 '12 at 20:48
  • 7
    while this is proper advice, it doesn't answer the question asked – Corey Goldberg Jan 20 '17 at 16:29
  • 2
    While packaging is a topic, there are a lot of other use cases, for example a deployment script written in python. – hoefling Feb 02 '17 at 18:58
5

for installing multiple packages, i am using a setup.py file with following code:

import sys
import subprocess
import pkg_resources

required = {'numpy','pandas','<etc>'} 
installed = {pkg.key for pkg in pkg_resources.working_set}
missing = required - installed


if missing:
    # implement pip as a subprocess:
    subprocess.check_call([sys.executable, '-m', 'pip', 'install',*missing])
Tanmay Shrivastava
  • 91
  • 1
  • 2
  • 10
1

Try the below. So far the best that worked for me Install the 4 ones first and then Mention the new ones in the REQUIRED list

import pkg_resources
import subprocess
import sys
import os

REQUIRED = {
  'spacy', 'scikit-learn', 'numpy', 'pandas', 'torch', 
  'pyfunctional', 'textblob', 'seaborn', 'matplotlib'
}

installed = {pkg.key for pkg in pkg_resources.working_set}
missing = REQUIRED - installed

if missing:
    python = sys.executable
    subprocess.check_call([python, '-m', 'pip', 'install', *missing], stdout=subprocess.DEVNULL)
Rijin
  • 51
  • 3
0
import os
os.system('pip install requests')

I tried above for temporary solution instead of changing docker file. Hope these might be useful to some

Janarthanan Ramu
  • 1,057
  • 10
  • 15