3

To view the installed libraries on an environment I run this code within a Jupyter Python notebook cell :

%%bash
pip freeze

This works, but how to conditionally execute this code ?

This is my attempt :

from __future__ import print_function
from ipywidgets import interact, interactive, fixed, interact_manual
import ipywidgets as widgets

def f(x1):
    if(x1 == True):
        f2()
    return x1

interact(f , x1 = False)


def f2():
    %%bash 
    pip freeze

But evaluating the cell throws error :

  File "<ipython-input-186-e8a8ec97ab2d>", line 15
    pip freeze
             ^
SyntaxError: invalid syntax

To generate the checkbox I'm using ipywidgets : https://github.com/ipython/ipywidgets

Update : Running pip freeze within check_call returns 0 results : enter image description here

Running

    %%bash 
    pip freeze

Returns installed libraries so 0 is not correct.

Is subprocess.check_call("pip freeze", shell=True) correct ?

Update 2 :

This works :

from __future__ import print_function
from ipywidgets import interact, interactive, fixed, interact_manual
import ipywidgets as widgets
import subprocess

def f(View):
    if(View == True):
        f2()

interact(f , View = False)


def f2():
    print(subprocess.check_output(['pip', 'freeze']))
blue-sky
  • 51,962
  • 152
  • 427
  • 752

2 Answers2

3

You can just use the standard Python way:

import subprocess
print(subprocess.check_output(['pip', 'freeze']))

Then your function will work in any Python environment.

John Zwinck
  • 239,568
  • 38
  • 324
  • 436
  • @blue-sky The result code from `check_call` is zero when the command succeeded, so it's entirely correct (but apparently not what you expect; but then what *do* you expect?) – tripleee Mar 13 '17 at 13:01
  • Though you want to avoid the unnecessary and pesky `shell=True`; see http://stackoverflow.com/questions/3172470/actual-meaning-of-shell-true-in-subprocess – tripleee Mar 13 '17 at 13:02
  • @blue-sky: Try the updated version--with explicit printing. – John Zwinck Mar 13 '17 at 13:18
1

The short explanation is that the notebook has interactive commands which are handled by the notebook itself, before the Python interpreter even sees them. %%bash is an example of such a command; you cannot put this in Python code, because it's not Python.

Using bash doesn't actually add anything here per se; using the shell offers many interactive benefits, and of course, in an interactive notebook, offering the user access to the shell is a powerful mechanism for allowing users to execute external processes; but in this particular case, with noninteractive execution, there are no actual benefits from putting the shell between yourself and pip, so you might simply want

 import subprocess
 if some_condition:
     p = subprocess.run(['pip', 'freeze'],
         stdout=subprocess.PIPE, universal_newlines=True)

(Notice the absence of shell=True because we don't need or want the shell here.)

If you want the captured exit code or the output from pip freeze they are available as attributes of the returned object p. See the subprocess.run documentation for details. Briefly, p.returncode will be 0 if the command succeeded, and the output will be in p.stdout.

Older versions of Python had a diverse collection of special-purpose wrappers around subprocess.Popen like check_call, check_output, etc. but these have all been subsumed by subprocess.run in recent versions. If you need to support Python versions before 3.5, the legacy functions are still available, but they should arguably be avoided in new code.

tripleee
  • 175,061
  • 34
  • 275
  • 318