Question

J'ai une application qui génère des fichiers journaux volumineux> 500MB.

Je l'ai écrit quelques utilitaires en Python qui me permet de parcourir rapidement le fichier journal et trouver des données d'intérêt. Mais je reçois maintenant des ensembles de données où le fichier est trop grand pour charger tout en mémoire.

Je veux donc numériser le document une fois, construire un index, puis charger uniquement la partie du document en mémoire que je veux regarder à la fois.

Cela fonctionne pour moi quand j'ouvre un « fichier » lire une ligne à la fois et stocker le décalage avec de file.tell (). Je peux alors revenir à cette section du fichier plus tard avec file.seek (offset, 0).

Mon problème est cependant que je puisse avoir UTF-8 dans les fichiers journaux, alors je dois les ouvrir avec le module codecs (de codecs.open(<filename>, 'r', 'utf-8')). Avec l'objet résultant je peux appeler et dire chercher, mais ils ne correspondent pas.

Je suppose que les codecs doit faire une mise en mémoire tampon ou peut-être il retourne caractère qui compte au lieu d'octets de dire?

Y at-il un moyen de contourner cela?

Était-ce utile?

La solution

Si cela est vrai, cela ressemble à un bug ou une limitation du module codecs, car il est un octet probablement confus et décalages de caractères.

J'utiliser la fonction open() régulière pour ouvrir le fichier, puis seek() / tell() vous donnera l'octet des décalages qui sont toujours cohérentes. Chaque fois que vous voulez lire, utilisez f.readline().decode('utf-8').

Attention cependant, que l'utilisation de la fonction f.read() peut vous débarquez au milieu d'un caractère multi-octets, produisant ainsi une erreur de décodage UTF-8. readline() toujours travailler.

Cela ne veut pas transparente gérer la marque d'ordre d'octet pour vous, mais les chances sont vos fichiers journaux ne sont BOM de toute façon.

Autres conseils

Pour UTF-8, vous n'avez pas réellement besoin d'ouvrir le fichier avec codecs.open. Au lieu de cela, il est fiable pour lire le fichier en tant que première chaîne d'octets, et ne décode alors une section individuelle (invoquant la méthode .decode sur la chaîne). Briser le fichier aux limites de la ligne est sûr; la seule façon de le diviser dangereux serait au milieu d'un caractère multi-octets (que vous pouvez reconnaître à partir de sa valeur d'octet> 128).

Une grande partie de ce qui se passe avec UTF8 en python est logique si vous regardez la façon dont il a été fait en Python 3. Dans votre cas, ça va faire un peu plus de sens que si vous lisez le chapitre Fichiers de plongée en Python 3 : http://diveintopython3.org/files.html

Le court, cependant, est que le travail de file.seek et file.tell avec des positions d'octets, alors que les caractères unicode peuvent prendre plusieurs octets. Ainsi, si vous faites:

f.seek(10)
f.read(1)
f.tell()

Vous pouvez facilement obtenir autre chose que 17, en fonction de la longueur du personnage que vous lisez un était.

Mise à jour: vous ne pouvez pas rechercher / dire sur l'objet retourné par codec.open (). Vous devez utiliser un fichier normal, et décoder les chaînes unicode à la lecture.

Je ne sais pas pourquoi cela ne fonctionne pas, mais je ne peux pas le faire fonctionner. SEEK semble fonctionner qu'une seule fois, par exemple. Ensuite, vous devez fermer et rouvrir le dossier, ce qui est bien sûr pas utile.

Le tell ne pas utiliser les positions de caractère, mais ne vous montre pas où votre position dans le flux est (mais probablement où l'objet de fichier sous-jacent est en lecture à partir du disque).

Donc probablement à cause d'une sorte de mise en mémoire tampon sous-jacente, vous ne pouvez pas le faire. Mais deocding après la lecture fonctionne très bien, alors allez pour cela.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top