Python 3 - Pouvons pickle poignée d'octets des objets de plus de 4 GO?
Sur cette base commentaire et les documents référencés, Cornichon 4.0+ de Python 3.4+ devrait être en mesure de pickle octet des objets de plus de 4 GO.
Cependant, l'utilisation de python 3.4.3 ou python 3.5.0b2 sur Mac OS X 10.10.4, j'ai une erreur quand j'essaie de pickle un grand tableau d'octets:
>>> import pickle
>>> x = bytearray(8 * 1000 * 1000 * 1000)
>>> fp = open("x.dat", "wb")
>>> pickle.dump(x, fp, protocol = 4)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
OSError: [Errno 22] Invalid argument
Est-il un bug dans mon code ou je suis incompréhension de la documentation?
- Il n'y a pas de problème pour moi. Python 3.4.1 sur Windows.
- Les pauses sur OS X. Ce n'est pas en réalité rien à voir avec de la saumure.
open('/dev/null', 'wb').write(bytearray(2**31 - 1))
fonctionne, maisopen('/dev/null', 'wb').write(bytearray(2**3))
jette l'erreur. Python 2 n'ont pas ce problème. - Ce qui déclenche une erreur pour vous fonctionne pour moi avec Python 2.7.10 et Python 3.4.3 (sur OS X, MacPorts versions).
- Je suis en utilisant Homebrew de Python.
- Avez-vous installer Python 3 à partir de Homebrew?
open('/dev/null','wb').write(bytearray(2**31)
échoue pour moi aussi avec la MacPort du python 3.4.3.- Je vois: il y a une faute de frappe dans Blender commentaire (
(3)
au lieu de(31)
, qui fait plus de sens étant donné le contexte). Avec ce changement, j'observe le même comportement que @Blender. - Les deux fonctionnent très bien sur 2.7.9 de homebrew et le stock OS X binaire.
- De même pour MacPorts' Python 2.7.10 sur OS X 10.10.
- Blender du test ci-dessus (avec
2**31
au lieu de2**3
) montre qu'il y a un bug dans Python 3.4.3 (Homebrew et MacPorts) sur OS X:open()
devrait être capable d'écrire un fichier de 4 GO. Je vais vérifier si cela a été signalé, et je vais faire un rapport de bogue dans le cas contraire. - Bug signalé: bugs.python.org/issue24658.
- Je pense que cela peut ne rien avoir à faire avec Python 3.4.x lui-même, mais la façon dont vous avez compilé votre interprète -- je n'ai pas de problèmes sur Mac OS X btw
- Je vais voter pour fermer cette question hors-sujet parce que c'est un bug en Python. Nous ne pouvons pas le résoudre, seulement le contourner.
- Donc qu'est ce qu'un travail autour de décapage et de l'onu-le décapage des fichiers volumineux? Le bug ne semble pas être résolu.
- Si vous savez que vous venez d'avoir un
bytes
objet, vous pouvez l'écrire comme-est (c'est à direwith open(something) as f: f.write(your_data_here)
; peut-être ajouter un champ de longueur à l'aide destruct.pack()
). C'est seulement quand vous avez besoin de conserver les informations de type ou d'envoyer quelque chose de plus complexe que la simplebytes
objets de décapage devient nécessaire. Même alors, vous pouvez souvent obtenir loin avec JSON ou d'une autre, plus simple format.
Vous devez vous connecter pour publier un commentaire.
Voici une solution simple pour question 24658. Utilisation
pickle.loads
oupickle.dumps
et de briser les octets de l'objet en morceaux de taille2**31 - 1
pour l'obtenir dans ou hors de le fichier.write
Devraitfor idx in range(0, n_bytes, max_bytes):
êtrefor idx in range(0, len(bytes_out), max_bytes):
range(0, n_bytes, max_bytes)
, devrait-il êtrerange(0, len(bytes_out), max_bytes)
? La raison je suggère, c'est (sur ma machine, de toute façon),n_bytes = 1024
, maislen(bytes_out) = 1062
, et pour les autres à venir à cette solution, vous êtes seulement en utilisant la longueur de votre fichier d'exemple, ce qui n'est pas nécessairement utile pour des scénarios du monde réel.Pour résumer ce qui a été répondu dans les commentaires:
Oui, Python peut pickle octet des objets plus gros que 4 GO. L'erreur observée est causé par un bug dans la mise en œuvre (voir Issue24658).
Ici, c'est la pleine solution de contournement, mais il semble que les cornichons.la charge n'essaie plus de vidage d'un fichier énorme plus (je suis sur Python 3.5.2) donc strictement parlant, seul le cornichon.décharges besoin pour fonctionner correctement.
La lecture d'un fichier par 2 go de morceaux prend deux fois plus de mémoire que nécessaire si
bytes
concaténation est effectuée, mon approche de la chargement cornichons est basé sur bytearray:Utilisation:
pickle.load(MacOSFile(fin))
sur linux, cela va casser, c'est exact? @markhorwrite
méthode?Vous pouvez spécifier le protocole pour l'image.
Si vous ne
pickle.dump(obj,file,protocol=4)
il devrait fonctionner.J'ai aussi trouvé ce problème, pour résoudre ce problème, j'ai le morceau de code en plusieurs itérations. Disons que dans ce cas j'ai 50.000 données que j'ai à calc tf-idf et ne knn classfication. Quand je lance directement et itérer 50.000 à me donner "erreur". Donc, pour résoudre ce problème, je chunk il.
Eu le même problème et qu'il est corrigé par la mise à niveau vers Python 3.6.8.
Cela semble être le PR qu'il a fait: https://github.com/python/cpython/pull/9937