Jak odczytać linie z pliku mm?
Wygląda na to, że interfejs mmap obsługuje tylko readline (). Jeśli próbuję iterację nad obiektem, otrzymuję znak zamiast pełnych linii.
Jaka byłaby metoda "pythoniczna" odczytu pliku mmap wiersz po wierszu?
import sys
import mmap
import os
if (len(sys.argv) > 1):
STAT_FILE=sys.argv[1]
print STAT_FILE
else:
print "Need to know <statistics file name path>"
sys.exit(1)
with open(STAT_FILE, "r") as f:
map = mmap.mmap(f.fileno(), 0, prot=mmap.PROT_READ)
for line in map:
print line # RETURNS single characters instead of whole line
4 answers
Najbardziej zwięzłym sposobem iteracji po liniach mmap
jest
with open(STAT_FILE, "r+b") as f:
map_file = mmap.mmap(f.fileno(), 0, prot=mmap.PROT_READ)
for line in iter(map_file.readline, b""):
# whatever
Zauważ, że w Pythonie 3 parametr sentinel iter()
musi być typu bytes
, podczas gdy w Pythonie 2 musi być str
(tj. ""
zamiast b""
).
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-02-04 19:17:39
Zmodyfikowałem twój przykład tak:
with open(STAT_FILE, "r+b") as f:
m=mmap.mmap(f.fileno(), 0, prot=mmap.PROT_READ)
while True:
line=m.readline()
if line == '': break
print line.rstrip()
Sugestie:
- nie wywołaj zmiennej
map
, jest to funkcja wbudowana. - Otwórz plik w
r+b
mode , jak w przykładzie Pythona na stronie pomocymmap
. W obu przypadkach należy podać deskryptor pliku otwartego do aktualizacji . Zobacz http://docs.python.org/library/mmap.html#mmap.mmap . - lepiej nie używać
UPPER_CASE_WITH_UNDERSCORES
zmiennej globalnej nazwy, jak wspomniano w globalnych nazw zmiennych w https://www.python.org/dev/peps/pep-0008/#global-variable-names . w innych językach programowania (takich jak C), stałe są często zapisywane wielkimi literami.
Edit: zrobiłem kilka testów czasu na Linuksie, ponieważ komentarz mnie zaciekawił. Oto porównanie timingów wykonanych na 5 sekwencyjnych uruchomieniach na pliku tekstowym 137mb.
Normalny dostęp do pliku:
real 2.410 2.414 2.428 2.478 2.490
sys 0.052 0.052 0.064 0.080 0.152
user 2.232 2.276 2.292 2.304 2.320
mmap
dostęp do pliku:
real 1.885 1.899 1.925 1.940 1.954
sys 0.088 0.108 0.108 0.116 0.120
user 1.696 1.732 1.736 1.744 1.752
Te terminy nie zawierają print
Oświadczenia (wykluczyłem go). Po tych numerach powiedziałbym, że dostęp do plików mapowanych w pamięci jest nieco szybszy.
Edit 2: używając python -m cProfile test.py
otrzymałem następujące wyniki:
5432833 2.273 0.000 2.273 0.000 {method 'readline' of 'file' objects}
5432833 1.451 0.000 1.451 0.000 {method 'readline' of 'mmap.mmap' objects}
Jeśli się nie mylę to mmap
jest trochę szybszy.
Dodatkowo wydaje się, że not len(line)
działa gorzej niż line == ''
, przynajmniej tak interpretuję wyjście profilera.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-11-27 00:56:54
Następujące są dość zwięzłe:
with open(STAT_FILE, "r") as f:
m = mmap.mmap(f.fileno(), 0, prot=mmap.PROT_READ)
while True:
line = m.readline()
if line == "": break
print line
m.close()
Zauważ, że line
zachowuje nowy wiersz, więc możesz chcieć go usunąć. Jest to również powód, dla którego if line == ""
robi właściwe rzeczy(pusta linia jest zwracana jako "\n"
).
Oryginalna iteracja działa tak, jak działa, ponieważ mmap
próbuje wyglądać zarówno jak plik, jak i łańcuch znaków. Wygląda jak ciąg dla celów iteracji.
Nie mam pojęcia, dlaczego nie może (lub nie chce) dostarczyć readlines()/xreadlines()
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-11-16 13:24:25
Python 2.7 32bit w Windows jest ponad dwa razy szybszy na pliku mm:
Na 27MB, 509k pliku tekstowego linii (moja funkcja 'parse' nie jest interesująca, głównie tylko readline () jest bardzo szybko):
with open(someFile,"r") as f:
if usemmap:
m=mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ)
else:
m=f
e.parse(m)
Z MMAP:
read in 0.308000087738
Bez MMAP:
read in 0.680999994278
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-12-29 03:48:08