如何有条件地评估 bash 脚本

How to conditionally evaluate bash script

要查看环境中已安装的库,我 运行 Jupyter Python notebook 单元中的此代码:

%%bash
pip freeze

这行得通,但是如何有条件地执行这段代码?

这是我的尝试:

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

但是评估单元格会抛出错误:

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

我正在使用 ipywidgets 生成复选框:https://github.com/ipython/ipywidgets

更新: 运行 pip freeze check_call returns 0 个结果:

运行

    %%bash 
    pip freeze

Returns 安装库所以 0 不正确。

subprocess.check_call("pip freeze", shell=True) 正确吗?

更新 2:

这个有效:

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']))

您可以使用标准 Python 方式:

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

那么您的函数将在任何 Python 环境中工作。

简短的解释是,notebook 具有由 notebook 本身处理的交互式命令,甚至在 Python 解释器看到它们之前。 %%bash 是此类命令的示例;你不能把它放在 Python 代码中,因为它不是 Python.

使用 bash 实际上并没有在此处添加任何东西 本身; 使用 shell 提供了许多交互好处,当然,在交互中notebook,为用户提供对 shell 的访问权限是允许用户执行外部进程的强大机制;但在这种特殊情况下,通过非交互式执行,将 shell 放在你自己和 pip 之间并没有实际好处,所以你可能只是想要

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

(请注意缺少 shell=True,因为我们不需要或不需要此处的 shell。)

如果您想要捕获的退出代码或 pip freeze 的输出,它们可用作返回对象 p 的属性。有关详细信息,请参阅 subprocess.run documentation。简而言之,如果命令成功,p.returncode 将为 0,并且输出将在 p.stdout.

旧版本的 Python 有多种围绕 subprocess.Popen 的特殊用途包装器集合,例如 check_callcheck_output 等,但这些都已包含在subprocess.run 在最近的版本中。如果您需要支持 3.5 之前的 Python 版本,遗留功能仍然可用,但可以说在新代码中应避免使用它们。