Tout en travaillant sur un script complètement différent, j'ai appris qu'avec 29 millions de lignes de texte, l'utilisation seek()
et l'exploitation des données par octets sont souvent plus rapides que ligne par ligne. La même idée est appliquée dans le script ci-dessous: nous ouvrons le fichier, et au lieu de parcourir en boucle l'ouverture et la fermeture du fichier (ce qui peut ajouter des frais généraux, même si cela n'est pas significatif), nous gardons le fichier ouvert et cherchons au début.
#!/usr/bin/env python3
from __future__ import print_function
import sys,os
def error_out(string):
sys.stderr.write(string+"\n")
sys.exit(1)
def read_bytewise(fp):
data = fp.read(1024)
print(data.decode(),end="",flush=True)
while data:
data = fp.read(1024)
print(data.decode(),end="",flush=True)
#fp.seek(0,1)
def main():
howmany = int(sys.argv[1]) + 1
if not os.path.isfile(sys.argv[2]):
error_out("Needs a valid file")
fp = open(sys.argv[2],'rb')
for i in range(1,howmany):
#print(i)
fp.seek(0)
read_bytewise(fp)
fp.close()
if __name__ == '__main__': main()
Le script lui-même est assez simple à utiliser:
./repeat_text.py <INT> <TEXT.txt>
Pour un fichier texte de 3 lignes et 1000 itérations, cela se passe très bien, environ 0,1 seconde:
$ /usr/bin/time ./repeat_text.py 1000 input.txt > /dev/null
0.10user 0.00system 0:00.23elapsed 45%CPU (0avgtext+0avgdata 9172maxresident)k
0inputs+0outputs (0major+1033minor)pagefaults 0swaps
Le script lui-même n'est pas le plus élégant, pourrait probablement être raccourci, mais fait le travail. Bien sûr, j'ai ajouté quelques bits supplémentaires ici et là, comme la error_out()
fonction, ce qui n'est pas nécessaire - c'est juste une petite touche conviviale.