Während ich an einem völlig anderen Skript arbeitete, habe ich gelernt, dass mit 29 Millionen Textzeilen das Verwenden seek()
und Bearbeiten von Daten nacheinander oft schneller ist als nacheinander. Dieselbe Idee wird im folgenden Skript angewendet: Wir öffnen eine Datei, und anstatt die Datei in einer Schleife zu öffnen und zu schließen (was zu zusätzlichem Aufwand führen kann, auch wenn dieser nicht signifikant ist), lassen wir die Datei geöffnet und versuchen, zum Anfang zurückzukehren.
#!/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()
Das Skript selbst ist recht einfach zu bedienen:
./repeat_text.py <INT> <TEXT.txt>
Für eine 3-zeilige Textdatei und 1000 Iterationen geht es ganz gut, ungefähr 0,1 Sekunden:
$ /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
Das Drehbuch selbst ist nicht besonders elegant, könnte wahrscheinlich gekürzt werden, macht aber den Job. Natürlich habe ich hier und da ein paar zusätzliche Elemente hinzugefügt, wie z. B. die error_out()
Funktion, die nicht erforderlich ist - es ist nur eine kleine benutzerfreundliche Berührung.