web-dev-qa-db-ja.com

Python3はgzipファイルを書き込みます-memoryview: 'str'ではなく、バイトのようなオブジェクトが必要です

ファイルを書きたいのですが。ファイルの名前に基づいて、これはgzipモジュールで圧縮される場合とされない場合があります。これが私のコードです:

import gzip
filename = 'output.gz'
opener = gzip.open if filename.endswith('.gz') else open
with opener(filename, 'wb') as fd:
    print('blah blah blah'.encode(), file=fd)

書き込み可能なファイルをバイナリモードで開き、書き込む文字列をエンコードしています。ただし、次のエラーが発生します。

File "/usr/lib/python3.5/gzip.py", line 258, in write
  data = memoryview(data)
TypeError: memoryview: a bytes-like object is required, not 'str'

オブジェクトがバイトではないのはなぜですか? 'w'でファイルを開き、エンコード手順をスキップすると、同じエラーが発生します。ファイル名から'.gz'を削除すると、同じエラーが発生します。

Ubuntu 16.04でPython3.5を使用しています

15
nic

printは比較的複雑な関数です。ファイルにstrを書き込みますが、渡したstrは書き込みません。パラメータのレンダリング結果であるstrを書き込みます。

すでにバイトがある場合は、fd.write(bytes)を直接使用して、必要に応じて改行を追加することができます。

バイトがない場合は、fdを開いてテキストを受信して​​ください。

6
Javier

このようにバイトに変換できます。

import gzip 
with gzip.open(filename, 'wb') as fd:
   fd.write('blah blah blah'.encode('utf-8'))
8

私にとっては、gzipフラグを'wt'に変更するとうまくいきました。元の文字列を、「バイト」することなく書くことができました。 (python 3.5、3.7、ubuntu 16でテスト済み)。

From python 3 gzip doc -quoting: "... mode引数は、「r」、「rb」、「a」、「ab」、「w」、「wb」、バイナリモードの場合は「x」または「xb」、テキストモードの場合はまたは「rt」、「at」、「wt」、または「xt」 ... "

import gzip

filename = 'output.gz'
opener = gzip.open if filename.endswith('.gz') else open
with opener(filename, 'wt') as fd:
    print('blah blah blah', file=fd)

!zcat output.gz
> blah blah blah
6
mork

pickleを使用してシリアル化できます。

最初にobjectをシリアル化して、pickleを使用して書き込み、次にgzipを使用します。

To save the object

import gzip, pickle
filename = 'non-serialize_object.Zip'
# serialize the object    
serialized_obj = pickle.dumps(object)
# writing Zip file
with gzip.open(filename, 'wb') as f:
   f.write(serialized_obj)

To load the object

import gzip, pickle
filename = 'non-serialize_object.Zip'

with gzip.open(filename, 'rb') as f:    
   serialized_obj = f.read()
# de-serialize the object
object = pickle.loads(serialized_obj)
0
imanzabet