python 脚本中的 Bash 源代码
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/30475980/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Bash source in a python script
提问by aquavitae
I am writing a wrapper python script which needs to source ./config
before running some other tools. Excluding the extra functionality that my script provides, it basically does this:
我正在编写一个包装 python 脚本,source ./config
在运行其他一些工具之前需要它。排除我的脚本提供的额外功能,它基本上是这样做的:
$ source ./config
$ ./a-tool.sh --args
$ ./another-tool.py --arg1 --arg2
Translating to python, I can do something along the lines of this to call the two scripts:
转换为 python,我可以做一些类似的事情来调用这两个脚本:
subprocess.call(['./a-tool.sh', '--args'])
subprocess.call(['./another-tool.py', '--arg1', '--arg2'])
But I can't figure out how to source
first, using the modified environment for the tools. I have read Emulating Bash 'source' in Python, but it suggests some hacks to modify the environment of running script which is not what I want.
但我无法弄清楚如何source
首先使用工具的修改环境。我已经在 Python 中阅读了Emulating Bash 'source',但它提出了一些修改运行脚本环境的技巧,这不是我想要的。
EDIT:
编辑:
To clarify, my script is currently a bash script which does a series of checks, parses some arguments, and depending on the outcome runs one or more tools as described above. The source
line is not always needed, and is not always the same. However, when it is used, all the following tools need to run in the same environment (i.e. bash process). In bash, this is easy. However, I want to rewrite the script in python because some of the other functionality is just easier for me to write and maintain in python. It is purely a language choice based on preference and has nothing to do with the actual functionality. Based on the answer by @abarnert, I guess I could do something like
澄清一下,我的脚本目前是一个 bash 脚本,它执行一系列检查、解析一些参数,并根据结果运行一个或多个如上所述的工具。这source
条线并不总是需要的,也不总是一样的。但是在使用的时候,下面所有的工具都需要运行在同一个环境中(即bash进程)。在 bash 中,这很容易。但是,我想用 python 重写脚本,因为其他一些功能对我来说在 python 中编写和维护更容易。它纯粹是一种基于偏好的语言选择,与实际功能无关。根据@abernert 的回答,我想我可以做类似的事情
subprocess.call(['source', '.config', ';', './a-tool.sh', ...])
That does not look easy to debug though, so I would prefer something like:
不过,这看起来并不容易调试,所以我更喜欢这样的:
bash = subprocess.run('bash')
bash.execute('source ./config')
bash.execute('a-tool.sh --args')
Is there any way to do this in python?
有没有办法在python中做到这一点?
回答by abarnert
All source
does is run the script in the context of the current bash
interpreter.
所有source
没有在当前的上下文中运行的脚本bash
解释器。
The Python interpreter is not a bash
interpreter, so what you're asking doesn't make any sense.*
Python解释器不是bash
解释器,所以你问的没有任何意义。*
Usually, all source
is used for is affecting environment variables, so that's what those "hacks" you linkedare doing. That isn't really a hack. It assumes that the script has no effect other than to set environment variables—but that should be a good assumption; if not, then whatever else it does is just something you can't do in Python anyway.
通常,所有source
用于影响环境变量,这就是您链接的那些“黑客”正在做的事情。那不是真正的黑客。它假定脚本除了设置环境变量外没有其他作用——但这应该是一个很好的假设;如果没有,那么它所做的任何其他事情都只是您在 Python 中无法做的事情。
Alternatively, you can create a bash
subprocess, and use that to source
the script and then run the other programs, instead of running each program directly as a subprocess of Python. (Whether by building a script on the fly, or feeding it non-tty stdin.) This is the only truly safe way to do everything that a sourced script could possibly do (because it's the only way to actually source the script).
或者,您可以创建一个bash
子进程,并将其用于source
脚本,然后运行其他程序,而不是将每个程序作为 Python 的子进程直接运行。(无论是通过动态构建脚本,还是提供非 tty 标准输入。)这是执行源脚本可能执行的所有操作的唯一真正安全的方法(因为这是实际获取脚本的唯一方法)。
Or, as a slightly different hack, concatenate each command onto the end of the script you want to source
and run it as a separate bash
subprocess. That will usuallywork, as long as none of the children try to change things in their parent environment or the like.
或者,作为稍微不同的 hack,将每个命令连接到您想要的脚本的末尾,source
并将其作为单独的bash
子进程运行。这通常会奏效,只要没有一个孩子试图改变他们父母环境或类似环境中的事情。
* It mayhave bash
as a parent…?but it may just as easily not… and, even if it did, that still wouldn't do what you want, unless the only thing you're trying to do is affect environment variables.
* 它可能有bash
作为父级......?但它可能同样容易没有......而且,即使它做了,仍然不会做你想要的,除非你试图做的唯一一件事就是影响环境变量。
回答by smassey
I agree with @Leon in the comments: switch the role of who executes what.
我同意@Leon 在评论中的观点:切换执行者的角色。
#!/bin/bash
source /my/conf.sh
python /my/script-1.py
python /my/script-2.py
The sourced bash config can export ENV variables and then from python you can read them with os.environ[].
源 bash 配置可以导出 ENV 变量,然后您可以从 python 中使用 os.environ[] 读取它们。
This is, AFAIK, the accepted methodfor these sorts of problems.
AFAIK,这是解决此类问题的公认方法。
回答by seven7e
I don't think you can do that actually. Because while using source somefile
in bash, somefile
will be executed in the SAME process as the main script. Thus the environment variables will be available in the main script if you put some export
statements in somefile
.
我不认为你实际上可以做到这一点。因为source somefile
在 bash 中使用时,somefile
会在与主脚本相同的进程中执行。因此,如果您将一些export
语句放入somefile
.
But, in your situation, python will create a new process (as a child of the process corresponding to current python script) and doing the source
operation. After that, the process will end and be destroyed. Yes, the source
operation was done successfully, but in the child process. The environment variables in parent process are available in child process, but NOT vice versa.
但是,在您的情况下,python 将创建一个新进程(作为与当前 python 脚本对应的进程的子进程)并执行source
操作。之后,该过程将结束并被销毁。是的,source
操作成功完成,但在子进程中。父进程中的环境变量在子进程中可用,但反之则不行。
You should follow the link which you put in the question. In that process, environment variables are created in the current process, i.e. the process which runs your python script.
您应该按照您在问题中提供的链接进行操作。在该进程中,环境变量在当前进程中创建,即运行您的python 脚本的进程。