如何"来源"文件到python脚本

时间:2016-04-30 19:07:14

标签: python bash python-2.7

我有一个文本文件/etc/default/foo,其中包含一行:

FOO="/path/to/foo"

在我的python脚本中,我需要引用变量FOO。

" source"最简单的方法是什么?文件/etc/default/foo进入我的python脚本,就像我在bash中做的那样?

. /etc/default/foo

7 个答案:

答案 0 :(得分:10)

您可以使用execfile

execfile("/etc/default/foo")

但请注意,这会将文件内容评估为您的程序源。除非您完全信任来源,否则存在潜在的安全隐患。

这也意味着该文件需要是有效的python语法(您的给定示例文件是)。

答案 1 :(得分:3)

如果您知道某些它只包含VAR="QUOTED STRING"个样式变量,请执行以下操作:

FOO="some value"

然后你可以这样做:

>>> with open('foo.sysconfig') as fd:
...   exec(fd.read())

哪个可以帮到你:

>>> FOO
'some value'

(这实际上与execfile()解决方案相同 在另一个答案中建议。)

这种方法具有重大的安全隐患;如果您的文件包含FOO="some value",而不是os.system("rm -rf /")

>>> with open('foo.sysconfig') as fd:
...   settings = {var: shlex.split(value) for var, value in [line.split('=', 1) for line in fd]}

那你就麻烦了。

或者,你可以这样做:

settings

它会为您提供一个字典>>> settings {'FOO': ['some value']} ,其中包含:

settings = {...}

for行正在使用http://www.postgresql.org/message-id/CFF47E56EA077241B1FFF390344B5FC10ACB1C0C@webmail.begavalley.nsw.gov.au。你可以用更多的${somevar:-value_if_not_set}循环来完成同样的事情。等等。

当然,如果文件包含像rcells = r.cells这样的shell样式变量扩展,那么这不会起作用(除非你编写自己的shell样式变量解析器)。

答案 2 :(得分:3)

请注意,如果您的“文本”文件中包含.py作为文件扩展名的内容,您可以随时执行以下操作:

{{1}}

当然,这假设文本文件在语法上是正确的,就Python而言。在我参与的项目中,我们做了类似的事情。将一些文本文件转换为Python文件。古怪,但也许值得考虑。

答案 3 :(得分:3)

只是提供不同的方法,请注意,如果您的原始文件设置为

export FOO=/path/to/foo

您可以执行source /etc/default/foo; python myprogram.py(或. /etc/default/foo; python myprogram.py),并且在myprogram.py内,在源文件中导出的所有值都在os.environ中可见,例如

import os
os.environ["FOO"] 

答案 4 :(得分:2)

答案与@jil相同,但该答案特定于某些历史版本的Python。

在现代Python(3.0或更高版本)中:

exec()

替换execfile()

答案 5 :(得分:1)

有几种方法可以做到这一点。

  • 您确实可以import将该文件作为模块,只要它包含的数据与python的语法相对应即可。但是,相关文件与您的脚本位于同一目录中.py,您要么使用imp(或importlib,具体取决于您的版本){{3 }}

  • 另一个解决方案(我有偏好)可以使用任何python库都可以解析的数据格式(作为一个例子,我想到了JSON)。

/ etc / default / foo:

{"FOO":"path/to/foo"}

在你的python代码中:

import json

with open('/etc/default/foo') as file:
    data = json.load(file)
    FOO = data["FOO"]
    ## ...
    file.close()

这样,你就不会冒险执行一些不确定的代码......

您可以选择,具体取决于您的喜好。如果您的数据文件是由某些脚本自动生成的,那么保留FOO="path/to/foo"之类的简单语法并使用imp可能会更容易。

希望它有所帮助!

答案 6 :(得分:0)

解决方案

这是我的方法:自己解析bash文件并仅处理变量赋值行,例如:

FOO="/path/to/foo"

以下是代码:

import shlex

def parse_shell_var(line):
    """
    Parse such lines as:
        FOO="My variable foo"

    :return: a tuple of var name and var value, such as
        ('FOO', 'My variable foo')
    """
    return shlex.split(line, posix=True)[0].split('=', 1)

if __name__ == '__main__':
    with open('shell_vars.sh') as f:
        shell_vars = dict(parse_shell_var(line) for line in f if '=' in line)
    print(shell_vars)

如何运作

看一下这个片段:

        shell_vars = dict(parse_shell_var(line) for line in f if '=' in line)

这一行遍历shell脚本中的行,只处理那些具有等号的行(不是一种检测变量赋值的万无一失的方法,但最简单)。接下来,将这些行运行到函数parse_shell_var中,该函数使用shlex.split来正确处理引号(或缺少引号)。最后,这些碎片被组装成字典。该脚本的输出是:

{'MOO': '/dont/have/a/cow', 'FOO': 'my variable foo', 'BAR': 'My variable bar'}

以下是 shell_vars.sh 的内容:

FOO='my variable foo'
BAR="My variable bar"
MOO=/dont/have/a/cow
echo $FOO

讨论

这种方法有几个优点:

  • 它不执行shell(在bash或Python中),这避免了任何副作用
  • 因此,即使shell脚本的来源未知,也可以安全使用
  • 正确处理带或不带引号的值

这种方法并不完美,它有一些局限性:

  • 检测变量分配的方法(通过查找等号的存在)是原始的并且不准确。有一些方法可以更好地检测这些线,但这是另一天的话题
  • 它无法正确解析基于其他变量或命令构建的值。这意味着,对于以下行,它将失败:

    FOO=$BAR
    FOO=$(pwd)