J'ai un fichier texte contient plus de 10 millions de lignes. Des lignes comme celle-là: comme vous l'avez vu, le délimiteur est ";". Je voudrais trier ce fichier texte à l'aide de Python selon le deuxième élément. Je ne pouvais pas utiliser la fonction scission. Parce que cela provoque MemeError. Comment puis-je le gérer? p> p>
3 Réponses :
Ne triez pas 10 millions de lignes en mémoire. Diviser ceci en lots à la place:
Exécutez 100 traces de ligne 100K (à l'aide du fichier comme itérateur, associé à fusionner les fichiers triés. Voici un générateur de fusion que vous pouvez passer 100 fichiers ouverts et donner des lignes dans la commande triée. Écrivez à une nouvelle ligne de fichier par ligne: p>
islice () code> ou similaire à choisir un lot). Écrire pour séparer les fichiers ailleurs. P> li>
import operator
def mergeiter(*iterables, **kwargs):
"""Given a set of sorted iterables, yield the next value in merged order
Takes an optional `key` callable to compare values by.
"""
iterables = [iter(it) for it in iterables]
iterables = {i: [next(it), i, it] for i, it in enumerate(iterables)}
if 'key' not in kwargs:
key = operator.itemgetter(0)
else:
key = lambda item, key=kwargs['key']: key(item[0])
while True:
value, i, it = min(iterables.values(), key=key)
yield value
try:
iterables[i][0] = next(it)
except StopIteration:
del iterables[i]
if not iterables:
raise
Cette technique est également appelée tri externe .
Vous pouvez le faire avec un os.System () code> appel à la fonction Bash Trier code>
basé sur Tri d'un million Entier 32 bits en 2 Mo de RAM à l'aide de Python : HASPQ.MERGE () CODE> a . Vous pouvez essayer Paramètre CODE> depuis Python 3.5 Mergeiter () Code> de Martijn Pieters 'Réponse à la place ou faire Transformer Schwartzian sur des versions plus anciennes Python: P> $ python sort-k2-n.py < input.txt > output.txt
HePq.Merge () sera ajouté à Python 3.5.
Pouvez-vous montrer le code que vous avez essayé?
Donc, vous dites que vous ne pouvez pas charger le fichier en mémoire?
C'est seulement environ 380 Mo de données. Courez-vous cela sur un téléphone?
@jordanm: double que lorsque vous utilisez un système d'exploitation 64 bits. 800 Mo pour un Python 64 bits 3.3 Build et l'OP permettent à Python décoder les données de fichier au lieu de le traiter comme binaire.
Si vous utilisez LIRE () et que vous lisez le fichier entier en mémoire, il s'agira d'une gamme de chaînes que pourrait i> remplir votre mémoire. Essayez de lire la ligne de fichier par ligne, en stockant un tuple de trois éléments de flotteurs / INTS. Cela devrait être beaucoup plus efficace de mémoire et vous pourrez peut-être vous faire pression sur votre mémoire.
@ Andrélaszlo: La chaîne (même en tant que données Unicode) prend moins d'octets, en fait. Les types de Python Int et de flotteur ont besoin d'un peu plus une fois converti.
@martjin Pouvez-vous élaborer? SYS.GETSIZEOF (37024469) -> 24 SYS.GETSIZEOF ("37024469") -> 48. Même les chaînes vides semblent prendre 40 octets, tandis que les entiers jusqu'à 10 ^ 18 prennent 24 octets. Évidemment, ces choses peuvent être spécifiques à la mise en œuvre.
@Martijnpieters: Vous avez complètement raison, bien sûr. Ma faute. Ma suggestion mange presque trois fois la mémoire :)
@george: Vous devez comparer une chaîne avec 2 entiers et une valeur de flotteur à la place.
Assez juste, mais si vous stockez uniquement des lignes entières telles que des chaînes, votre algorithme de tri devra analyser la chaîne à chaque fois qu'il a besoin de la valeur. Peut-être stocker des tuples de la forme (int (champ2), une chaîne entière) est optimale ..
@george: Il suffit d'analyser chaque ligne une fois de trier, de sorte que vous le permettez également pendant i> Tri:
lignes.sort (clé = lambda l: int (l.split ( ';'; ', 2) [1])) code>.