web-dev-qa-db-fra.com

Fichier gzip d'écriture Python3 - memoryview: un objet de type octets est requis, pas 'str'

Je veux écrire un fichier. En fonction du nom du fichier, celui-ci peut ou non être compressé avec le module gzip. Voici mon code:

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)

J'ouvre le fichier inscriptible en mode binaire et j'encode ma chaîne à écrire. Cependant, j'obtiens l'erreur suivante:

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

Pourquoi mon objet n'est-il pas un octet? J'obtiens la même erreur si j'ouvre le fichier avec 'w' et ignorer l'étape de codage. J'obtiens également la même erreur si je supprime le '.gz' à partir du nom de fichier.

J'utilise Python3.5 sur Ubuntu 16.04

15
nic

print est une fonction relativement complexe. Il écrit str dans un fichier mais pas le str que vous passez, il écrit le str qui est le résultat du rendu des paramètres.

Si vous avez déjà des octets, vous pouvez utiliser fd.write(bytes) directement et prendre soin d'ajouter une nouvelle ligne si vous en avez besoin.

Si vous n'avez pas d'octets, assurez-vous que fd est ouvert pour recevoir du texte.

6
Javier

vous pouvez le convertir en octets comme celui-ci.

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

Pour moi, changer l'indicateur gzip en 'wt' a fait le travail. Je pourrais écrire la chaîne d'origine, sans la "contourner". (testé sur python 3.5, 3.7 sur ubuntu 16).

From python 3 gzip doc - quoting: "... L'argument mode peut être n'importe lequel de 'r', 'rb', 'a', 'ab', 'w', 'wb', 'x' ou 'xb' pour le mode binaire, ou 'rt', 'at', 'wt' ou 'xt' pour le mode texte . .. "

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

Vous pouvez le sérialiser en utilisant pickle.

Sérialisez d'abord le object à écrire à l'aide de pickle, puis à l'aide de gzip.

Pour enregistrer le 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)

Pour charger le 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