6

My question relates to this question: Installing python module within code, but involves upgrading the module.

I've tried

packages=['apscheduler','beautifulsoup4','gdata']

def upgrade(packages):
    for package in packages:
        pip.main(['install --upgrade', package])

and

def upgrade(packages):
    for package in packages:
        pip.main(['install', package + ' --upgrade'])
3
  • Did you try pip.main(['install', '--upgrade', package])? Commented Sep 16, 2014 at 6:58
  • no i didn't. I know I should be flogged. what do i do with the question now? delete it? Commented Sep 16, 2014 at 7:00
  • I added it as answer, if it works you can accept it. Commented Sep 16, 2014 at 7:01

3 Answers 3

14

Try pip.main(['install', '--upgrade', package]).

"--upgrade" is a separate command-line argument, so you need to pass it separately to main.

Sign up to request clarification or add additional context in comments.

1 Comment

from pip._internal import main as main is moved to internal. see: stackoverflow.com/a/50764560/6306190
2

BrenBarn's answer matches the style of OP's code, but Richard Wheatley's answer is closer to my code.

Richard's answer has a couple of issues I'd like to fix, though, and I didn't want to edit his because the differences are reasonably significant.

from subprocess import call

my_packages = ['apscheduler', 'beautifulsoup4', 'gdata']

def upgrade(package_list):
    call(['pip', 'install', '--upgrade'] + package_list)

Notes:

  • No need to import the pip module (subprocess calls the pip binary found in its path)
  • Unecessary use of shell=True in call() (and other subprocess functions) should be be avoided, as it puts responsibility on the programmer to protect against shell injection vulnerabilities. (Not really an issue here, but good as a general rule.)
  • A single invocation of pip install accepts an arbitrary number of package names, and a single use of --upgrade will apply to all of them.
  • We can leverage the previous fact and Python's list concatenation to avoid writing a loop.

Comments

0

I now this is an old thread but I have come across it many times and I think I should give another solution since I've used this one. To me this is more user-friendly.

import pip
from subprocess import call

packages=['apscheduler','beautifulsoup4','gdata']

def upgrade(packages):
    for package in packages:
        call("pip install --upgrade " + package, shell=True)

After reading the following Actual meaning of 'shell=True' in subprocess post, it appears that the shell=True command was not needed and is probably not the best idea. import pip is not needed since I do not call pip.main as was seen in some previous answers.

So the new code could be: from subprocess import call

packages=['apscheduler','beautifulsoup4','gdata']

def upgrade(packages):
    for package in packages:
        call("pip install --upgrade " + package)

As for the other answers, I prefer passing the specific string and loop. You will not get a performance hit or gain using either method.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.