it-swarm-ja.com

なぜノードまたはpython readコマンドで設定された数値変数にアクセスできないのですか?

観察:数値のみの値を含むオペレーティングシステムの「読み取り」ユーティリティを使用して設定された環境変数は、Pythonのos.environ[]構造またはノードのprocess.env構造ではアクセスできませんが、bashではアクセスできます。

予想される動作は、作成方法に関係なく、すべての環境変数にアプリケーションから等しくアクセスできることです。

export N=12345構文を使用してbashを使用して設定した場合、同じ変数にアクセスできます。 readコマンドを使用して作成された変数は、他の変数と同じように作成されていないため、ノード/ Pythonのこれらの変数の解析ロジックが妨げられているようです。

以下のechoステートメントに示すように、node/Pythonからアクセスできない同じ変数には、bashコマンドラインから簡単にアクセスできます。

Readコマンドは、キー入力に基づいて環境変数を設定します。これは、シークレットの.bash_historyレコードを残さずに、シークレットを変数に入力する便利な方法です。

複製:

  • OSX 10.14.6( "Mojave")Python 2.7、Python 3.6、ノード10.16.3 Linux
  • カーネル3.10CentOS 64ビット、Python2.7.5

サンプル:

readを使用して、Lという名前の環境変数の値を入力するようにユーザーに促します。

~ $ read L
12345
~ $ python2
Python 2.7.16 (default, Apr 12 2019, 15:32:40) 
[GCC 4.2.1 Compatible Apple LLVM 10.0.1 (clang-1001.0.46.3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> os.environ["L"]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/Cellar/[email protected]/2.7.16/Frameworks/Python.framework/Versions/2.7/lib/python2.7/UserDict.py", line 40, in __getitem__
    raise KeyError(key)
KeyError: 'L'
>>> 
~ $ python3
Python 3.7.3 (default, Mar 27 2019, 09:23:15) 
[Clang 10.0.1 (clang-1001.0.46.3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> os.environ["L"]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/Cellar/python/3.7.3/Frameworks/Python.framework/Versions/3.7/lib/python3.7/os.py", line 678, in __getitem__
    raise KeyError(key) from None
KeyError: 'L'
~ $ echo $L
12345

興味深いことに、数値変数が読み取りコマンド以外の方法で設定されている場合、それらはPythonおよびノー​​ドでアクセス可能です。

>>> os.environ["HISTSIZE"]
'12345678'
1
regulatre

シェルでは、環境変数を操作していません– Shell変数を操作しています。シェルは、初期環境のcopyで始まりますが、独自の変数名前空間を維持します。

シェル変数は環境にのみコピーされます「エクスポート」フラグがある場合。真新しい変数はデフォルトではエクスポートされません–問題ではありませんhowそれらが生成された場合でも、exportコマンドを使用して正しいフラグを設定する必要があります。

$ read L
12345↵

$ export L

$ python -c 'import os; print("L is", os.environ["L"])'
L is 12345

これはreadに固有のものではないことに再度注意してください。 exportを使用せずに変数を設定しただけでも、同じ失敗が見られます。

$ N=abcdef

$ python -c 'import os; print("N is", os.environ["N"])'
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/usr/lib/python3.7/os.py", line 678, in __getitem__
    raise KeyError(key) from None
KeyError: 'N'

Bashでは、declare -p VARを使用して、その変数に現在環境へのエクスポートのフラグが設定されているかどうかを確認できます(フラグが設定されている場合は、-xオプションがあります)。

$ declare -p L N
declare -x L="12345"       # the one that was exported in example 1
declare -- N="abcdef"      # the one that deliberately wasn't, in example 2

(出力は入力として有効です。たとえば、実際にrundeclare -xの場合、これはexportと同等です。)


雑記:

  • 環境には文字列値のみを含めることができますが、シェル変数はそれだけに限定されません。たとえば、ほとんどのシェルには配列/リストとdictがあります。

  • シェルには、エクスポートしない変数が含まれていることがよくありますwant。たとえば、$ LINESと$ COLUMNSはシェル自体の中で動的ですが、それらをエクスポートすると、プログラムに静的な値しか表示されないため、これはwould問題を引き起こします。

2
user1686