LINUX.ORG.RU

[PyGTK] Чтение больших файлов — как правильнее.

 


0

1

Приветствую.

Интересует вопрос как лучше организовать чтение больших текстовых файлов в PyGtk, чтоб не замораживался интерфейс. Для определенности будем считать большим файл объема в 20-30 Мб.

На данный момент в голове крутятся идеи с потоками (threading.Thread) и чтением маленькими кусками с вызовом gtk.main_iteration() между чтениями. Также подумывал об использовании gio.File() с его async методами, но так и не нашел способа сделать seek по файлу при async чтении (нужно для дочитывания лог-файлов). К тому же для чтения сжатых файлов надо ставить gvfs которая в большинстве дистрибутивов тянет пол гнума.

Ваши идеи?

★★★★★

Ответ на: комментарий от Eddy_Em

>mmap и читать кусками?

Какой нафиг mmap в пистоне? И потом мне интересно не то как именно читать кусками, а чем лучше посегментное чтение по сравнению с чтением в отдельном потоке.

fat_angel ★★★★★
() автор топика
Ответ на: комментарий от fat_angel

ты думаешь весь файл сразу в память пихается, а не последовательно через итератор читается? или я чего-то недопонял

anonymous
()
Ответ на: комментарий от anonymous

>или я чего-то недопонял

Конечно, почитай про gtk.main_loop() в частности и про event-driven модели вообще.

fat_angel ★★★★★
() автор топика

Правильнее выкинуть пистон.

anonymous
()
Ответ на: комментарий от fat_angel

Я к тому, что при построчном чтении после чтения определенно числа строк придется вызывать код вида:

while gtk.events_pending():
    gtk.main_iteration()
для того, чтоб интерфейс реагировал на действия пользователя произошедшие во время чтения.

Мне интересно чем это лучше чтения в отдельном потоке (кроме простоты). И какие еще альтернативы можно придумать.

fat_angel ★★★★★
() автор топика
Ответ на: комментарий от Eddy_Em

При чем тут вообще управление памятью? Ты с фризами GUI при выполнении продолжительных операций пока не сталкивался что ли?

fat_angel ★★★★★
() автор топика
Ответ на: комментарий от fat_angel

Ну, подумаешь - фриз на 1-2 секунды... Если правильно работать с памятью - ничего такого не будет.

А можно совместить: читать отдельным потоком, а основному лишь отдавать готовый буфер.

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от fat_angel

mmap на файл вспомогательному потоку, выделение стационарного буфера для основного, взаимодействие сигналами...

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от schizoid

4.2

AIO во все поля

Правда, не знаю, как там в пистоне - смапили те опции, что надо, или как обычно.

Еще можно погуглить доку glib/gtk. Учитывая, что в glib запилили собственные потоки, будет верх странности, если они их не примастырили асинхронную работу с ними в gtk.

LamerOk ★★★★★
()
Ответ на: комментарий от LamerOk

Учитывая, что в glib запилили собственные потоки

В pygtk их нет, печаль. Может в новом GObject'е который с GI оно есть.

будет верх странности, если они их не примастырили асинхронную работу с ними в gtk.

async методы у gio.File() наверное как раз оно и есть, но как я писал там похоже нет возможности seek'ать файлы.

fat_angel ★★★★★
() автор топика
Ответ на: комментарий от fat_angel

Всякое бывает... Главное вспомнить)

pylin ★★★★★
()

В gtk есть еще idle функции. Можно пристыковать такую к main_loop и она будет автоматом периодически выполняться пока ее не отстыкуете. Можно через нее читать небольшими порциями.

hibou ★★★★★
()
Ответ на: комментарий от fat_angel

> как я писал там похоже нет возможности seek'ать файлы.

seek'ать файл можно «обычным» способом, для этого не нужен async метод.

LamerOk ★★★★★
()

1) В питоновском потоке с idle вызовом функции, которая будет выводить данные. Чтобы не плясать с локами.

2) gio.

baverman ★★★
()

Пример через gio.

import gtk
import gio
import glib
import threading
import time

window = gtk.Window(gtk.WINDOW_TOPLEVEL)
window.set_default_size(400, 400)
window.connect('delete-event', gtk.main_quit)

sw = gtk.ScrolledWindow()
window.add(sw)

view = gtk.TextView()
sw.add(view)

window.show_all()

def main():
    t = threading.Thread(target=writer, args=(open('/tmp/big.file', 'w'),))
    t.daemon = True
    t.start()

    f = gio.file_parse_name('/tmp/big.file')
    instream = f.read()
    instream.read_async(1024, reader)

    return False

def writer(f):
    while True:
        f.write('String\n')
        f.flush()
        time.sleep(0.01)

def reader(instream, result):
    b = view.get_buffer()
    b.insert(b.get_end_iter(), instream.read_finish(result))
    instream.read_async(1024, reader)

glib.idle_add(main)

gtk.threads_init() # Нужно только чтобы запустить writer

gtk.main()

baverman ★★★
()
Ответ на: комментарий от baverman

Спасибо за пример с GIO. Я недоглядел, что у gio.InputStream() тоже есть async-методы. Наверное на него и переведу весь IO, чтоб не плясать с бубном вокруг чтения сжатых файлов.

Кстати хочу спросить — у меня одного возникает ощущение, что API GIO писался под веществами?

fat_angel ★★★★★
() автор топика
Ответ на: комментарий от fat_angel

у меня одного возникает ощущение, что API GIO писался под веществами?

Поначалу тоже было. Но это вполне обосновано целями: предоставить единый api для работы с любыми файловыми системами. Слишком сложно абстрагироваться от нюансов, поэтому иногда он кажется мутноватым.

baverman ★★★
()
Ответ на: комментарий от true_admin

>import mmap

Вот это дааа!… Даже и не знал о существовании такого.

fat_angel ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.