Je suis en train d'écrire un module qui permet entre autre au niveau du bit d'accès en lecture aux fichiers. Les fichiers peuvent être grandes (des centaines de GO) j'ai donc écrit une classe simple qui me permet de traiter le fichier comme une chaîne et se cache l'ensemble de la recherche et de la lecture.
Au moment où j'ai écrit ma classe wrapper je ne connaissais pas le mmap module. À la lecture de la documentation pour mmap j'ai pensé "grand - c'est juste ce dont j'avais besoin, je vais prendre mon code et de le remplacer avec un mmap. C'est probablement beaucoup plus efficace et il est toujours bon de supprimer le code."
Le problème est que mmap ne fonctionne pas pour les gros fichiers! C'est très surprenant pour moi que je pensais que c'était peut-être l'application la plus évidente. Si le fichier est au-dessus de quelques gigaoctets puis-je obtenir un EnvironmentError: [Errno 12] Cannot allocate memory
. Cela se produit uniquement avec un 32 bits Python construire de sorte qu'il semble qu'il est en cours d'exécution hors de l'espace d'adresse, mais je ne trouve pas de documentation sur ce sujet.
Mon code est juste
f = open('somelargefile', 'rb')
map = mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ)
Donc ma question est suis-je raté quelque chose d'évident ici? Est-il un moyen d'obtenir mmap à travailler de façon portable sur de gros fichiers, ou dois-je retourner à mon naïf fichier wrapper?
Mise à jour: Il semble y avoir un sentiment que le Python mmap devraient avoir les mêmes restrictions que la POSIX mmap. Pour mieux exprimer ma frustration ici est une simple classe qui a une petite partie de la fonctionnalité de mmap.
import os
class Mmap(object):
def __init__(self, f):
"""Initialise with a file object."""
self.source = f
def __getitem__(self, key):
try:
# A slice
self.source.seek(key.start, os.SEEK_SET)
return self.source.read(key.stop - key.start)
except AttributeError:
# single element
self.source.seek(key, os.SEEK_SET)
return self.source.read(1)
Elle est en lecture seule et ne pas faire quelque chose de compliqué, mais je peux faire la même avec un mmap:
map2 = Mmap(f)
print map2[0:10]
print map2[10000000000:10000000010]
sauf qu'il n'y a pas de restrictions sur la taille des fichiers. Pas trop difficile, vraiment...