从Python中获取Bash脚本的好方法是什么?
我有一个基本的采购职能:从Python中获取Bash脚本的好方法是什么?,python,bash,dictionary,env,Python,Bash,Dictionary,Env,我有一个基本的采购职能: def source( fileName = None, update = True ): pipe = subprocess.Popen(". {fileName}; env".format( fileName = fileName ), stdout = subprocess.PIPE, shell = True) data = pipe.communicate()[0] env = dic
def source(
fileName = None,
update = True
):
pipe = subprocess.Popen(". {fileName}; env".format(
fileName = fileName
), stdout = subprocess.PIPE, shell = True)
data = pipe.communicate()[0]
env = dict((line.split("=", 1) for line in data.splitlines()))
if update is True:
os.environ.update(env)
return(env)
当我尝试使用它来生成特定脚本时,会出现以下错误:
>>> source("/afs/cern.ch/sw/lcg/contrib/gcc/4.8/x86_64-slc6/setup.sh")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 9, in source
ValueError: dictionary update sequence element #51 has length 1; 2 is required
闭合链支架位于第51行
如何从Python中以健壮、合理的方式获取Bash脚本,从而避免此类错误(以及您可能想到的任何其他错误)?您看到的这行代码是脚本执行以下操作的结果:
module() { eval `/usr/bin/modulecmd bash $*`; }
export -f module
from subprocess import Popen, PIPE
# The commented-out line really should not be necessary; it's impossible
# for an environment variable name to contain an =. However, it could
# be replaced with a more stringent check.
prog = ( r'''from os import environ;'''
+ r'''from sys import stdout;'''
+ r'''stdout.write("\0".join("{k}={v}".format(kv)'''
+ r''' for kv in environ.iteritems()'''
#+ r''' if "=" not in kv[0]'''
+ r''' ))'''
)
# Lots of error checking omitted.
def getenv_after_sourcing(fn):
argv = [ "bash"
, "-c"
, '''. "{fn}"; python -c '{prog}' '''.format(fn=fn, prog=prog)]
data = Popen(argv, stdout=PIPE).communicate()[0]
return dict(kv.split('=', 1) for kv in data.split('\0'))
也就是说,它显式地导出bash
函数模块
,以便sub(bash)shell可以使用它
我们可以从环境变量的格式告诉我们,在SHILLASH补丁的中间升级了BASH。我不认为当前有一个补丁会生成
BASH\u FUNC\u module()=
而不是BASH\u FUNC\u module%%()=
,但iirc在一系列修复过程中发布了这样一个补丁。现在事情已经解决了,您可能想再次升级bash。(如果这是剪切粘贴错误,请忽略此段落。)
我们还可以看出系统上的/bin/sh
是bash
,假设模块
函数是通过寻找shell脚本引入的
也许您应该决定是否关心导出的bash函数。您是想将模块
导出到您正在创建的环境中,还是忽略它?下面的解决方案只返回它在环境中找到的内容,因此它将包括模块
简言之,如果要分析某个试图打印环境的shell命令的输出,可能会遇到三个问题:
(){
开头,因此它们很容易识别。在shellshock之后,它们的名称将是BASH_FUNC_funcname%%
,但除非您在野外找不到经过预打补丁和后打补丁的BASH,否则您可能不想依赖它。)=
符号,并且一些实用程序将在没有=
符号的情况下打印出来module() { eval `/usr/bin/modulecmd bash $*`; }
export -f module
from subprocess import Popen, PIPE
# The commented-out line really should not be necessary; it's impossible
# for an environment variable name to contain an =. However, it could
# be replaced with a more stringent check.
prog = ( r'''from os import environ;'''
+ r'''from sys import stdout;'''
+ r'''stdout.write("\0".join("{k}={v}".format(kv)'''
+ r''' for kv in environ.iteritems()'''
#+ r''' if "=" not in kv[0]'''
+ r''' ))'''
)
# Lots of error checking omitted.
def getenv_after_sourcing(fn):
argv = [ "bash"
, "-c"
, '''. "{fn}"; python -c '{prog}' '''.format(fn=fn, prog=prog)]
data = Popen(argv, stdout=PIPE).communicate()[0]
return dict(kv.split('=', 1) for kv in data.split('\0'))
我认为通常最好直接使用bash来设置环境,然后在已经设置好的环境中调用python脚本 如果我正确理解了您的情况,那么您可以使用一些bash脚本来设置希望在python脚本中设置的环境。这些python脚本然后使用准备好的环境来为更多的工具设置更多的环境 我建议进行以下设置:
- 使用bash脚本设置环境
- 调用python设置脚本(python脚本从bash脚本继承环境)
- 在上面的bash脚本准备的环境中启动
- 继续为下一个工具准备环境
另一种方法是手动将bash脚本转换为python。为什么要用python编写shell脚本?您想做什么?将shell变量转换为python变量?遇到这些行时,您希望发生什么?您遇到的是bash shell脚本代码,而不仅仅是环境变量b实际上,我正在尝试运行一个Python脚本,该脚本设置了一个特定的环境,然后生成Python模块(实际上绑定到一个更大的基础设施)可用于导入。我正在尝试在运行源程序的Python环境中提供通过获取shell脚本创建的环境。我应该以什么方式进行此操作?我目前使用的基本方法根本不够可靠。但不是“Python模块”只是一个包含python文件的文件夹?(至少有一个文件名为
\uuu init\uuuuuuy.py
)。我会尝试回答你的问题,但你所说的目标对我来说没有意义。我不知道python脚本如何创建python模块。除非你也在脚本的文件系统中动态创建文件,(如果我错了,有人可以纠正我),您无法通过创建子流程来更改python进程的环境变量。在子流程生成bash脚本时,只有子流程的环境变量发生了更改。因此,退出后,脚本的进程将不会发生任何更改。在一般情况下,这可能是可能的,也可能是不可能的。在我的情况下,我需要从python中加载模块,depending在一些编程定义的情况下,因此您的方法不适用于该情况