【问题标题】:"source" to set PATH to bitbake with shell=True having no effect in Python"source" 将 PATH 设置为 bitbake,shell=True 在 Python 中无效
【发布时间】:2018-10-17 05:38:36
【问题描述】:

下面是shell脚本中的代码

source /proj/common/tools/repo/etc/profile.d/repo.sh
repo project init $branch
repo project sync
source poky/fnc-init-build-env build
bitbake -g $image

我正在尝试将 shell 脚本转换为 python 脚本

a = subprocess.call("source /proj/common/tools/repo/etc/profile.d/repo.sh", shell=True)
b = subprocess.call("repo project init " + branch, shell=True)
b2 = subprocess.call("repo project sync", shell=True)
c = subprocess.call("source poky/fnc-init-build-env build", shell=True)
os.chdir("poky/build")
d = subprocess.call("bitbake -g " + image, shell=True)

但我收到以下错误

/bin/sh: bitbake: command not found

如何在 python 中解决这个问题?

【问题讨论】:

  • 你安装了“bitbake”吗?
  • 否则您的安装在 $PATH 以外的目录中
  • subprocess.call("bitbake -g " + image, shell=True) 实际上比您替换它的 shell 错误得多。如果 image='$(touch /tmp/evil).jpg' 在 shell 中,那将是无害的;在您的 Python 中,它会创建一个不需要的文件(或运行嵌入在文件名中的任何其他命令)。如果您完全关心安全性或正确性,请使用shell=False
  • ...也就是说,直接关注的是,您 source repo.sh 所在的 shell 与您后来调用 bitbake -g 的 shell 完全不同.
  • ...所以,如果bitbake 仅在上述(sourcerepo 等)命令在同一个 shell 中运行后才可用,则将这些命令拆分为多个 subprocess.call() s 永远不会工作。

标签: python bash shell bitbake


【解决方案1】:

您必须将 bitbake 添加到路径:

set Path=%path%;PathOfBitbake

在 Windows 的命令提示符下运行它然后重试

【讨论】:

  • 由于 OP 使用 bash-only shell 命令,因此他们的平台似乎不太可能是 Windows。
  • @CharlesDuffy 他没有说明他的系统是 Windows 还是 Linux
  • 是的,但是source 命令是一个bashism(并且问题被标记为bash)。 Bash 不是 subprocess.call(..., shell=True) 在 Windows 上使用的。因此,在没有任何明确规范的情况下,很可能假定 OP 不在 Windows 上。
  • @CharlesDuffy 它不是真的,我尝试了 subprocess.Popen() 和 subprocess.call() 它给了我相同的结果(我在 Windows 上运行)
  • 什么相同的结果?当然当然你会得到bitbake: command not found。您无法尝试运行 source /proj/common/tools/repo/etc/profile.d/repo.sh,因为除了 OP 之外没有人拥有该 repo.sh 文件。
【解决方案2】:

问题是,您多次运行 subprocess.call(something, shell=True) 并假设在第一次调用中设置的变量存在于后来的调用中,这些调用使用独立于早期调用的 shell。

我会将命令放在一个 shell 脚本中,然后使用单个 subprocess.call 命令运行它。通过运行带有subprocess 模块的shell 命令,将其逐行转换为python 似乎没有任何意义。

repobitbake 是python 程序时,可能需要从它们导入相关模块并运行相应的python 函数,而不是它们的main 方法提供的shell 命令。

【讨论】:

    【解决方案3】:

    使用shell=True 时,第一个列表元素是要运行的脚本,随后的参数将传递给该脚本。

    每个subprocess.Popen() 调用启动一个shell;一个中配置的状态不会传递给其他状态,因此source 命令是无用的,除非您在同一调用中运行依赖于它的命令

    script='''
    branch=$1; shift  # pop first argument off the list, assign to variable named branch
    source /proj/common/tools/repo/etc/profile.d/repo.sh || exit
    repo project init "$branch" || exit
    repo project sync || exit
    source poky/fnc-init-build-env build || exit
    exec "$@"  # use remaining arguments to form our command to run
    '''
    
    subprocess.call([
        "bash", "-c", script,    # start bash, explicitly: /bin/sh does not support "source"
        "_",                     # becomes $0 inside the shell
        branch,                  # becomes $1, which is assigned to branch and shifted off
        "bitbake", "-g", image   # these arguments become "$@" after the shift
    ])
    

    请注意|| exits - 您通常应该在您不明确打算忽略失败的任何命令上使用它们。

    【讨论】:

    • 谢谢@Charles Duffy。它工作正常,但我需要它在 python 脚本中。
    • 我正在使用“linux machine & python version is 2.7”@Charles_Duffy
    • @PuneethKumar,这 Python。你不能在没有 bash shell 的情况下使用source,所以在你的 Python 脚本中嵌入一个 shell 脚本是绝对必要的,除非你重写你的 Python 来完成你在 sourceing 内部执行的所有脚本。显然,除非您将问题扩展到实际包含这些脚本的文本,否则我们无法告诉您如何执行此操作。
    • @PuneethKumar, ...无论如何,如果你想让你的原始代码成为纯 Python,没有 shell 依赖,你不能使用shell=True。由于问题包含shell=True,因此可以从您的 Python 代码中明确调用 shell 解释器。
    【解决方案4】:

    你需要添加'bitbake'的路径,所以它可以从你的python脚本中找到。

    sys.path.append(your_path_there)
    

    【讨论】:

    • sys.path 指的是 PYTHONPATH,而不是用于查找可执行文件的 PATH。
    猜你喜欢
    • 2021-04-20
    • 1970-01-01
    • 2019-10-19
    • 2013-09-25
    • 1970-01-01
    • 1970-01-01
    • 2020-06-02
    • 1970-01-01
    • 2012-10-01
    相关资源
    最近更新 更多