【问题标题】:Using Python to open a shell environment, run a command and exit environment使用Python打开shell环境,运行命令并退出环境
【发布时间】:2014-04-05 11:37:40
【问题描述】:

我正在尝试使用 python 自动化一个过程。如果我只是在终端中,工作流程如下所示:

user:> . /path/to/env1.sh
user:> python something.py
user:> exit
user:> . /path/to/env2.sh
user:> python something2.py
user:> exit 

等更多步骤。每个env.sh 都会生成一个新脚本,其中包含大量环境变量以及当前目录中未设置的内容。我很确定我需要使用子流程,但我不确定如何去做。理想情况下,工作流程应该是:打开新的 shell --> 运行一些命令 --> 退出 shell --> 必要时重复。

编辑:似乎需要澄清一下。我了解如何使用 subprocess.Popen()subprocess.call() 从调用 Python 脚本的 shell 中调用事物。这不是我需要的。当一个人调用env.sh 时,它会设置一大堆环境变量和一些其他相关的东西,然后让你进入一个 shell 来运行命令。重要的是要注意env.sh 不会终止,直到在运行所需的命令后键入exit。使用subprocess.call("./env.sh", shell = True) 打开外壳并停在那里。就像输入命令./env.sh 一样,除了当发出exit 命令时,其余的python 脚本。所以:

subprocess.call(". /path/to/env.sh", shell = True)
subprocess.call("python something.py", shell = True)

不做我需要做的事,也不做:

p = subprocess.Popen(". /path/to/env.sh", shell = True)
subprocess.call("python something.py", shell = True)
p.kill()

【问题讨论】:

  • 我的解决方案是使用 Popen.communcate() 但是我确实在让我的输入通过时遇到了一些麻烦,但我在这里找到了答案:stackoverflow.com/questions/12965023/… one need to import PIPE from subprocess to be能够将字符串传递给您的子进程。我不完全确定要选择哪个答案,因为它们都不是完全正确的,而且许多建议的模块都将被弃用。
  • 如果您认为自己知道答案,则将其发布为作为答案而不是评论并接受。

标签: python bash shell subprocess


【解决方案1】:

据我了解,您想运行一个命令,然后将其传递给其他命令:

from subprocess import Popen, PIPE

p = Popen("/path/to/env.sh", stdin=PIPE)   # set environment, start new shell
p.communicate("python something.py\nexit") # pass commands to the opened shell

【讨论】:

  • 但这与 OP 的代码现在正在做的事情不同。 . whateversource whatever 相同,基本上采用whatever 并在当前环境中运行。你可以把它想象成 C 的#include。 OP 正在使用它来设置环境变量,以便在执行 python 程序时,它具有正确的环境。您的解决方案通过 stdin 将 python something.py\nnext (作为字符串)传递给脚本——我不确定这有什么相同...
  • @mgilson: source whatever 对父级有 no 影响。如果您的目的是更改环境变量,那么调用call("source whatever", shell=True)毫无意义
  • 肯定会影响父母。这就是你使用它的原因。这就是为什么您在更改某些内容后执行source ~/.bashrc 的原因。你在当前环境中接受这些变化。 FWIW,我只是做了一个简单的测试,相当于:echo "export FOO=Bar" > foo.sh; . foo.sh; echo ${FOO},第二个echo 工作。你是想说这种变化不会传播到 python 中吗?我同意你的看法,但这不是问题所在。我们正在尝试在 python 中重现 OP 的 bash 代码——python 有不同的机制来设置子进程中的环境(正如我已经指出的那样)。
  • 我认为我们同意source,但不同意 OP 的评论。我认为 OP 只是 认为 他/她使用管道解决了问题(但实际上没有)...或者更改 env.sh 以评估从标准输入读取的输入(哎呀!) .
【解决方案2】:

你可以使用subprocess:

>>> import subprocess
>>> subprocess.call('python something.py', shell = True)

或者你可以使用os:

>>> import os
>>> os.system('python something.py')

这是一个例子(打开你的扬声器):

>>> import os
>>> os.system('say Hello')

【讨论】:

  • 我很欣赏这个答案,但在我的问题中,我规定命令需要在 /path/to/env.sh 打开的 shell 中运行,而不仅仅是我调用初始 python 脚本的 shell .
【解决方案3】:

subprocess 调用(特别是Popen)接受env 参数,该参数是环境变量到值的映射。你可以用那个。例如

env = {'FOO': 'Bar', 'HOME': '/path/to/home'}
process = subprocess.Popen(['python', 'something.py'], env=env)

当然,通常情况下,最好在 *import*ing something.py 之后调用一些函数,而不是产生一个全新的进程。

【讨论】:

【解决方案4】:

这是给你的help.... 对于运行命令,您可以这样做:

1)

from subprocess import call
call(["ls", "-l"])

2)

import os
os.system("command")

例子:

import os
f = os.popen('date')
now = f.read()
print "Today is ", now

要启用终端,您可以导入os 模块:

import os
os.system('python script.py')

或者如上所述,您可以使用import subprocess

【讨论】:

  • 我运行的命令需要在 /path/to/env.sh 打开的 shell 中,而不是调用父脚本的 shell。
  • 好的,看这个link
  • 阅读这些链接:123
  • 请不要推荐os.popen。它是“自 2.6 版起已弃用:此功能已过时。”
【解决方案5】:
p = subprocess.Popen(". /path/to/env.sh", shell = True, stdout=subprocess.PIPE).communicate()
subprocess.call("python something.py", shell = True).communicate()

【讨论】:

  • 这行不通。第一个命令的想法是为第二个命令设置环境。您在第一个命令中设置环境,但它不会传播回 python,因此当您执行第二个命令时,它仍然在与 python 相同的环境中执行。
  • -1:call() 返回一个整数(退出代码)。它没有.communicate() 方法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-10-15
  • 1970-01-01
  • 1970-01-01
  • 2011-08-20
  • 2017-11-09
  • 2023-03-11
  • 1970-01-01
相关资源
最近更新 更多