web-dev-qa-db-fra.com

_pickle en python3 ne fonctionne pas pour une grande sauvegarde de données

J'essaie de postuler _pickle pour enregistrer les données sur le disque. Mais lorsque vous appelez _pickle.dump, J'ai une erreur

OverflowError: cannot serialize a bytes object larger than 4 GiB

Est-ce une limitation difficile à utiliser _pickle? (cPickle pour python2)

31
Jake0x32

Pas plus dans Python 3.4 qui a PEP 3154 et Pickle 4.0
https://www.python.org/dev/peps/pep-3154/

Mais vous devez dire que vous souhaitez utiliser la version 4 du protocole:
https://docs.python.org/3/library/pickle.html

pickle.dump(d, open("file", 'w'), protocol=4)
61
Eric Levieil

Oui, c'est une limite codée en dur; de save_bytes fonction :

else if (size <= 0xffffffffL) {
    // ...
}
else {
    PyErr_SetString(PyExc_OverflowError,
                    "cannot serialize a bytes object larger than 4 GiB");
    return -1;          /* string too large */
}

Le protocole utilise 4 octets pour écrire la taille de l'objet sur le disque, ce qui signifie que vous ne pouvez suivre que des tailles allant jusqu'à 232 == 4 Go.

Si vous pouvez diviser l'objet bytes en plusieurs objets, chacun de moins de 4 Go, vous pouvez toujours enregistrer les données dans un cornichon, bien sûr.

4
Martijn Pieters

Il y a une grande réponse ci-dessus pour savoir pourquoi le cornichon ne fonctionne pas. Mais cela ne fonctionne toujours pas pour Python 2.7, ce qui est un problème si vous êtes toujours à Python 2.7 et que vous souhaitez prendre en charge des fichiers volumineux, en particulier NumPy (Les tableaux NumPy sur 4G échouent).

Vous pouvez utiliser la sérialisation OC, qui a été mise à jour pour fonctionner avec les données sur 4Gig. Il existe un module d'extension Python C disponible à partir de:

http://www.picklingtools.com/Downloads

Jetez un œil à la documentation:

http://www.picklingtools.com/html/faq.html#python-c-extension-modules-new-as-of-picklingtools-1-6-0-and-1-3-

Mais, voici un bref résumé: il y a des ocdumps et ocloads, tout comme les dumps et charges de pickle:

from pyocser import ocdumps, ocloads
ser = ocdumps(pyobject)   : Serialize pyobject into string ser
pyobject = ocloads(ser)   : Deserialize from string ser into pyobject

La sérialisation OC est 1,5 à 2 fois plus rapide et fonctionne également avec C++ (si vous mélangez des langages). Il fonctionne avec tous les types intégrés, mais pas avec les classes (en partie parce qu'il s'agit d'un langage croisé et qu'il est difficile de créer des classes C++ à partir de Python).

1
rts1