2017-06-11 1 views
3

どのようにPythonの環境変数からバイト列を設定しますか?

b'\x1b\xba\x94(\xae\xd0\xb2\xa6\xf2f\xf6\x1fI\xed\xbao$\xc6D\x08\xba\x81\x96v' 

、あなたがos.urandom(24)を経由して生成されたバイトの文字列を持っていることを言うと、あなたは、環境変数に

export FOO='\x1b\xba\x94(\xae\xd0\xb2\xa6\xf2f\xf6\x1fI\xed\xbao$\xc6D\x08\xba\x81\x96v' 

ていることに格納し、Pythonプログラム内から値を取得したいのですがos.environを使用してください。

foo = os.environ['FOO'] 

ここでの問題は、fooは、文字列リテラル値'\\x1b\\xba\\x94...代わりのバイトシーケンスb'\x1b\xba\x94...を持っている、ということです。

適切なexport値は何ですか、またはos.environを使用してFOOをバイト文字列として処理する方法はありますか?

+0

一重引用符が原因である可能性があります。 –

+0

私は混乱しています。あなたが 'os.urandom'のようなものから来て、' b '\ x1b \ xba ...'を見て、Pythonで(repr) 'foo'を印刷するなら、(Pythonで)生のバイトです。 envvarから読み込んで ''\\ x1b \\ xba''を見ると、まだエスケープされている(Unicode)文字列です。 [この質問](https://stackoverflow.com/questions/43214001/how-to-write-binary-data-in-bash)によると、bashはあなたの 'export FOO'行を実際と解釈しないようですバイナリですが、 '\ x'の束が入った文字列です。 –

答えて

2

はあなたがPythonで「アンエスケープ」あなたのバイトすることができますzwerの答えで

import os 
import sys 

if sys.version_info[0] < 3: # sadly, it's done differently in Python 2.x vs 3.x 
    foo = os.environ["FOO"].decode('string_escape') # since already in bytes... 
else: 
    foo = bytes(os.environ["FOO"], "utf-8").decode('unicode_escape') 
+0

あなたのPy3ソリューションは 'bytes'オブジェクトではなく' str'を生成し、文字列フォームを 'bytes'に不必要に変換します。この2行目を 'foo = os.environb [b'FOO '] .deode(' unicode-escape ')。encode(' latin-1 ')'で 'os.environb'(' ( 'latin-1'は、最初の256個のUnicodeの序数をバイトとして序数にマップする1-1のマッピングです)。 – ShadowRanger

0

は、私が試した次

のbashからの最初の(これは同じバイナリリテラルybakosによって与えられた)

export FOO='\x1b\xba\x94(\xae\xd0\xb2\xa6\xf2f\xf6\x1fI\xed\xbao$\xc6D\x08\xba\x81\x96v' 

私はPythonシェルを起動しました(私はPython 3.5.2を持っています)

>>> import os 
>>> # ybakos's original binary literal 
>>> foo = b'\x1b\xba\x94(\xae\xd0\xb2\xa6\xf2f\xf6\x1fI\xed\xbao$\xc6D\x08\xba\x81\x96v' 
>>> # ewer's python 3.x solution 
>>> FOO = bytes(os.environ["FOO"], "utf-8").decode('unicode_escape') 
>>> foo == FOO 
False 
>>> ^D 

foo == FOOの最後の行はtrueを返す必要があるため、解決策は正しく動作するようには見えません。

私はos.envirnb辞書があることに気づいたが、私は、バイナリリテラルに環境変数を設定するために見つけ出すことができなかったので、私は、バイナリリテラルのASCIIバージョンを取得するためにbase64エンコーディングを使用して、次の選択肢を試してみました。 bashシェルに続い

まず起動Pythonシェル

>>> import os 
>>> import base64 
>>> foo = os.urandom(24) 
>>> foo 
b'{\xd9q\x90\x8b\xba\xecv\xb3\xcb\x1e<\xd7\xba\xf1\xb4\x99\xf056\x90U\x16\xae' 
>>> foo_base64 = base64.b64encode(foo) 
>>> foo_base64 
b'e9lxkIu67Hazyx4817rxtJnwNTaQVRau' 
>>> ^D 

export FOO_BASE64='e9lxkIu67Hazyx4817rxtJnwNTaQVRau' 

そしてバックPythonシェルで

>>> import os 
>>> import base64 
>>> # the original binary value from the first python shell session 
>>> foo = b'{\xd9q\x90\x8b\xba\xecv\xb3\xcb\x1e<\xd7\xba\xf1\xb4\x99\xf056\x90U\x16\xae' 
>>> dec_foo = base64.b64decode(bytes(os.environ.get('FOO_BASE64'), "utf-8")) 
>>> # the values match! 
>>> foo == dec_foo 
True 
>>> ^D 

最後の行は2つの結果であることを示し同じ!!

私たちがやっていることは、まずos.urandom()とそれをエンコードするBase64からバイナリ値を取得します。次に、Base64エンコードされた値を使用して環境変数を設定します。注:base64.b64encode()はバイナリ値を返しますが、印刷可能なASCII文字のみを含みます。

次に、環境変数からBase64エンコード文字列値を読み込み、その文字列をバイナリ形式に変換し、最後にBase64で元の値にデコードします。

1

もう1つのオプションは、Bashでバイナリデータとして設定するだけです。これは、ANSI string quotingを使用します。

export FOO=$'\x1b\xba\x94(\xae\xd0\xb2\xa6\xf2f\xf6\x1fI\xed\xbao$\xc6D\x08\xba\x81\x96v' 
+0

これは、Pythonのデータを 'os.environ ['FOO']'(Py2)や 'os.environb [b'FOO ']'(Py3)と同じように読みやすくするので、素晴らしいアプローチです。 Pythonのデータを生の 'bytes'としてエンコードまたはデコードする必要はありません。私はBashのこの機能について完全に忘れてしまったので、思い出してくれてありがとう! – ShadowRanger

関連する問題