web-dev-qa-db-ja.com

python 3で失敗するbase64.encodestring

次のコードは、python 2マシンで正常に実行されます。

base64_str = base64.encodestring('%s:%s' % (username,password)).replace('\n', '')

Python 3に移植しようとしていますが、そうすると次のエラーが発生します。

>>> a = base64.encodestring('{0}:{1}'.format(username,password)).replace('\n','')
Traceback (most recent call last):
  File "/auto/pysw/cel55/python/3.4.1/lib/python3.4/base64.py", line 519, in _input_type_check
    m = memoryview(s)
TypeError: memoryview: str object does not have the buffer interface

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/auto/pysw/cel55/python/3.4.1/lib/python3.4/base64.py", line 548, in encodestring
    return encodebytes(s)
  File "/auto/pysw/cel55/python/3.4.1/lib/python3.4/base64.py", line 536, in encodebytes
    _input_type_check(s)
  File "/auto/pysw/cel55/python/3.4.1/lib/python3.4/base64.py", line 522, in _input_type_check
    raise TypeError(msg) from err
TypeError: expected bytes-like object, not str

エンコード文字列の使用例を検索してみましたが、適切なドキュメントを見つけることができませんでした。明らかなものがないのですか?これをRHEL 2.6.18-371.11.1.el5で実行しています

14
Vinay Pai

_base64.encodestring_に渡す前に、文字列を(バイト文字列に変換するために)encode()できます。例-

_base64_str = base64.encodestring(('%s:%s' % (username,password)).encode()).decode().strip()
_
20
Anand S Kumar

Anandの答え(これはかなり正しい)を拡張するために、Python 2は、「これはテキストのように扱いたい文字列です」と「ここは同じように扱いたい文字列です」をほとんど区別しませんでした。 Python 3は2つをしっかりと区別し、それらを混同させません。前者はstrタイプであり、後者はbytesタイプです。

文字列をBase64エンコードすると、実際には文字列をテキストとして扱うのではなく、一連の8ビットバイト値として扱います。 Python 3:でbase64.encodestring()からエラーが発生するのはそのためです。これは、文字列の文字をとして処理する操作であるためです8ビットバイトなので、bytes型のパラメーターではなく、str型のパラメーターを渡す必要があります。

したがって、strオブジェクトをbytesオブジェクトに変換するには、そのencode()メソッドを呼び出して、8ビットのバイト値のセットに変換する必要があります。使用することを選択したUnicodeエンコーディング。 (very specific理由がない限り、UTF-8にする必要がありますが、他のトピックを選択する必要があります)。

7
rmunn

Python 3でエンコード文字列のドキュメントは言う:

def encodestring(s): "" "encodebytes()のレガシーエイリアス" ""インポート警告warnings.warn( "encodestring()は非推奨のエイリアスです。encodebytes()を使用してください。DeprecationWarning、2)エンコードバイトを返します

Python 3.5.1の作業コードは次のとおりです。URLエンコードの方法も示しています。

def _encodeBase64(consumer_key, consumer_secret):
    """
     :type consumer_key: str
     :type consumer_secret: str
     :rtype str
    """
    # 1. URL encode the consumer key and the consumer secret according to RFC 1738.
    dummy_param_name = 'bla'
    key_url_encoded = urllib.parse.urlencode({dummy_param_name: consumer_key})[len(dummy_param_name) + 1:]
    secret_url_encoded = urllib.parse.urlencode({dummy_param_name: consumer_secret})[len(dummy_param_name) + 1:]

    # 2. Concatenate the encoded consumer key, a colon character “:”, and the encoded consumer secret into a single string.
    credentials = '{}:{}'.format(key_url_encoded, secret_url_encoded)

    # 3. Base64 encode the string from the previous step.
    bytes_base64_encoded_credentials = base64.encodebytes(credentials.encode('utf-8'))

    return bytes_base64_encoded_credentials.decode('utf-8').replace('\n', '')

(私はそれがより簡潔かもしれないと確信しています、私はPythonに新しいです...)

以下も参照してください: http://pythoncentral.io/encoding-and-decoding-strings-in-python-3-x/

2