web-dev-qa-db-ja.com

ファイルをpythonスクリプトに「ソース」する方法

テキストファイルがあります/etc/default/fooこれには1行が含まれます。

FOO="/path/to/foo"

pythonスクリプトでは、変数FOOを参照する必要があります。

ファイルを「ソース」にする最も簡単な方法は何ですか/etc/default/foo into pythonスクリプト、bashで行うのと同じ?

. /etc/default/foo
13
Martin Vegter

execfile を使用できます。

execfile("/etc/default/foo")

ただし、これによりファイルの内容がプログラムソースにそのまま評価されることに注意してください。ソースを完全に信頼できない限り、潜在的なセキュリティ上の危険があります。

また、ファイルは有効なpython構文(指定されたサンプルファイル))である必要があります。

11
jil

次のように_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ループなどを使用して、さらに数行で同じことを実現できます。

そしてもちろん、ファイルに_${somevar:-value_if_not_set}_のようなシェルスタイルの変数展開が含まれている場合、これは機能しません(独自のシェルスタイル変数パーサーを記述しない限り)。

4
larsks

ファイル拡張子が.pyであるこのコンテンツを含む「テキスト」ファイルがある場合は、いつでも実行できることに注意してください。

import mytextfile

print(mytestfile.FOO)

もちろん、これは、テキストファイルがPythonに関する限り、構文的に正しいことを前提としています。私が取り組んでいるプロジェクトで、これに似た何かをしました。いくつかのテキストファイルをPythonファイル。奇抜ですが、検討する価値があるかもしれません。

3
Harlin

別のアプローチを与えるために、元のファイルが

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"] 
3
Foon

@jilと同じ答えですが、その答えはPythonの歴史的なバージョンに固有のものです。

現代ではPython(3.0+):

_exec()
_

execfile()を置き換えます

2
Hack-R

この種のことを行うには、いくつかの方法があります。

  • 含まれるデータがPythonの構文に対応している限り、ファイルをモジュールとしてimportできます。ただし、問題のファイルは、スクリプトと同じディレクトリにある.pyであるか、imp(またはバージョンに応じてimportlib)を使用する必要があります ここのように

  • 別の解決策(私の好みがあります)は、任意の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を使用する方が簡単な場合があります。

それが役立つことを願っています!

1
Ascam

ソリューション

私のアプローチは次のとおりです。自分で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)

この行は、シェルスクリプト内の行を反復処理し、等号を持つ行のみを処理します(変数の割り当てを検出する確実な方法ではなく、最も単純な方法)。次に、これらの行を関数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

討論

このアプローチにはいくつかの利点があります。

  • シェルを実行せず(bashまたはPython)、副作用を回避します
  • したがって、シェルスクリプトの起源が不明な場合でも、使用しても安全です。
  • 引用符の有無にかかわらず値を正しく処理します

このアプローチは完全ではなく、いくつかの制限があります。

  • 変数の割り当てを検出する方法(等号の存在を探すこと)は原始的であり、正確ではありません。これらの行をより適切に検出する方法がありますが、それは別の日のトピックです
  • 他の変数またはコマンドに基づいて構築された値を正しく解析しません。つまり、次のような行では失敗します。

    FOO=$BAR
    FOO=$(pwd)
    
0
Hai Vu