web-dev-qa-db-fra.com

ValueError: pickle de chaîne non sécurisé

Lorsque j'essaie de charger quelque chose que j'ai vidé avec cPickle, le message d'erreur suivant s'affiche:

ValueError: insecure string pickle

Les tâches de déchargement et de chargement sont effectuées sur le même ordinateur, donc le même système d'exploitation: Ubuntu 8.04.

Comment pourrais-je résoudre ce problème?

46
Peter Long

"C’est beaucoup plus probable qu’un bogue jamais observé dans Python lui-même, dans une fonctionnalité utilisée des milliards de fois par jour à travers le monde": cela me surprend toujours de constater à quel point les gens se croisent dans ces forums.

Un moyen simple d’obtenir ce problème est d’oublier de fermer le flux que vous utilisez pour vider la structure de données. je viens de faire

>>> out = open('xxx.dmp', 'w')
>>> cPickle.dump(d, out)
>>> k = cPickle.load(open('xxx.dmp', 'r'))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: insecure string pickle

C'est pourquoi je suis arrivé ici en premier lieu, car je ne pouvais pas voir ce que j'avais mal fait.
.__ Et puis j'y ai réfléchi plutôt que de venir ici et j'ai réalisé que j'aurais dû le faire: 

>>> out = open('xxx.dmp', 'w')
>>> cPickle.dump(d, out)
>>> out.close() # close it to make sure it's all been written
>>> k = cPickle.load(open('xxx.dmp', 'r'))

Facile à oublier. Je n'ai pas besoin qu'on dise aux gens qu'ils sont des idiots.

85
Allan Ramsay

Vérifiez ce fil . Peter Otten dit:

Un cornichon corrompu. L'erreur est levé si une chaîne dans le vidage le fait ne pas commencer et se terminer par "ou".

et montre un moyen simple de reproduire une telle "corruption". Steve Holden, dans le post de suivi, suggère une autre façon de causer le problème serait de ne pas associer 'rb' et 'wb' (mais dans Python 2 et sous Linux, cette erreur particulière devrait passer inaperçue).

8
Alex Martelli

J'ai eu cette erreur dans Python 2.7 à cause du mode ouvert 'rb':

    with open(path_to_file, 'rb') as pickle_file:
        obj = pickle.load(pickle_file)

Donc, pour Python 2, le 'mode' devrait être 'r'

De plus, je me suis demandé si Python 3 ne supportait pas le format pickle de Python 2, et si vous essayez de charger un fichier pickle créé en Python 2, vous obtenez:

pickle.unpicklingerror: the string opcode argument must be quoted
7
Oleg Neumyvakin

Que faites-vous avec les données entre dump() et load()? C’est une erreur assez courante de stocker des données picklées dans un fichier ouvert en mode texte (sous Windows) ou dans un stockage de base de données d’une manière qui ne fonctionne pas correctement pour les données binaires (colonnes VARCHAR, TEXT dans certaines bases de données, certains stockages clé-valeur). Essayez de comparer les données picklées que vous transmettez au stockage et que vous récupérez immédiatement.

7
Denis Otkidach

Si quelqu'un a cette erreur à l'aide de youtube-dl, le problème est résolu: https://github.com/rg3/youtube-dl/issues/7172#issuecomment-242961695

richiecannizzo a commenté le août 28

brew install libav
Faut-il le réparer instantanément sur mac ou 

Sudo apt-get install libav
# sur linux 

7
Pysis

Cette erreur peut également se produire avec python 2 (et les premières versions de python 3) si votre cornichon est volumineux ( Problème Python n ° 11564 ):

Python 2.7.11 |Anaconda custom (64-bit)| (default, Dec  6 2015, 18:08:32) 
[GCC 4.4.7 20120313 (Red Hat 4.4.7-1)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
Anaconda is brought to you by Continuum Analytics.
Please check out: http://continuum.io/thanks and https://anaconda.org
>>> import cPickle as pickle
>>> string = "X"*(2**31)
>>> pp = pickle.dumps(string)
>>> len(pp)
2147483656
>>> ss = pickle.loads(pp)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: insecure string pickle

Cette limitation a été résolue avec l’introduction du protocole pickle 4 dans Python 3.4 ( PEP 3154 ). Malheureusement, cette fonctionnalité n'a pas été rétroportée vers Python 2 et ne le sera probablement jamais. Si tel est votre problème et que vous devez utiliser pickle Python 2, le mieux que vous puissiez faire est de réduire la taille de votre cornichon, par exemple, au lieu de mariner une list, décortiquez les éléments individuellement dans une list de cornichons.

5
Paul Price

Même problème avec un fichier créé avec python sous Windows et rechargé avec python sous Linux ..__ Solution: dos2unix sur le fichier avant d'être lu sous Linux: fonctionne comme un charme

4
am_technix

J'ai reçu le message Python ValueError: insecure string pickle d'une manière différente.

Pour moi, cela s'est passé après un base64 codant un fichier binaire et passant à travers les sockets urllib2.

Au départ, j'étais en train de boucler un fichier comme celui-ci

with open(path_to_binary_file) as data_file:
    contents = data_file.read() 
filename = os.path.split(path)[1]

url = 'http://0.0.0.0:8080/upload'
message = {"filename" : filename, "contents": contents}
pickled_message = cPickle.dumps(message)
base64_message = base64.b64encode(pickled_message)
the_hash = hashlib.md5(base64_message).hexdigest()

server_response = urllib2.urlopen(url, base64_message)

Mais sur le serveur, le hash continuait à sortir différemment pour certains fichiers binaires

decoded_message = base64.b64decode(incoming_base64_message)
the_hash = hashlib.md5(decoded_message).hexdigest()

Et unpickling a donné le message insecure string pickle

cPickle.loads(decoded_message)

MAIS SUCCÈS

Ce qui a fonctionné pour moi a été d'utiliser urlsafe_b64encode() 

base64_message = base64.urlsafe_b64encode(cPickle.dumps(message))

Et décoder avec

base64_decoded_message = base64.urlsafe_b64decode(base64_message)

Références

http://docs.python.org/2/library/base64.html

https://tools.ietf.org/html/rfc3548.html#section-3

3
HeyWatchThis

C’est ce qui m’est arrivé, peut-être une petite partie de la population, mais je tiens à le signaler ici néanmoins, pour eux:

L'interpréteur (Python3) vous aurait donné une erreur indiquant que le flux de fichier d'entrée devait être en octets, et non en tant que chaîne, et que vous avez peut-être changé l'argument de mode ouvert de "r" en "rb". en vous disant que la chaîne est corrompue, et c'est pourquoi vous êtes venus ici.

L’option la plus simple pour de tels cas consiste à installer Python2 (vous pouvez installer la version 2.7), puis à exécuter votre programme avec l’environnement Python 2.7 afin que votre fichier soit dépilé sans problème. Fondamentalement, j'ai perdu beaucoup de temps à analyser ma chaîne pour voir si elle était vraiment corrompue alors que tout ce que je devais faire était de changer le mode d'ouverture du fichier de rb en r, puis d'utiliser Python2 pour le dissocier. Donc, je ne fais que mettre cette information là-bas.

1
Arijit

J'ai rencontré ce problème plus tôt, trouvé ce fil, et supposé que j'étais immunisé contre le problème de fermeture de dossier mentionné dans une ou deux de ces réponses puisque j'utilisais une déclaration with:

with tempfile.NamedTemporaryFile(mode='wb') as temp_file:
    pickle.dump(foo, temp_file)

    # Push file to another machine
    _send_file(temp_file.name)

Cependant, comme je poussais le fichier temporaire de inside the with, le fichier n’était toujours pas fermé et le fichier que je poussais était donc tronqué. Cela a entraîné la même erreur insecure string pickle dans le script qui a lu le fichier sur la machine distante.

Deux solutions potentielles à cela: garder le fichier ouvert et forcer un vidage:

with tempfile.NamedTemporaryFile(mode='wb') as temp_file:
    pickle.dump(foo, temp_file)
    temp_file.flush()

    # Push file to another machine
    _send_file(temp_file.name)

Ou assurez-vous que le fichier est fermé avant de faire quoi que ce soit avec:

file_name = ''
with tempfile.NamedTemporaryFile(mode='wb', delete=False) as temp_file:
    file_name = temp_file.name
    pickle.dump(foo, temp_file)

# Push file to another machine
_send_file(file_name)
0
0x5453