LINUX.ORG.RU

python - память


0

0

Подскажите пожалуйста, как определить, где происходит утечка памяти в программе на питоне? Всем документам xml делаю unlink. За ночь сожрала 160 Мб =( Вкратце: приложение получает данные от сервера в виде XML и рисует графики в режиме реального времени.


Сначала нужно локализовать утечку: отключать некоторые фрагменты программы и смотреть, когда память перестанет утекать. Например, получать XML, но не строить графики, не получать XML и строить графики по сгенерированным данным (имитация).

Какие модули/библиотеки используются для работы с XML и рисования графиков? Можно поискать информацию, нет ли в каком из них такой ошибки и не исправлена ли она.

Если есть подозрения, что в питоновком коде не освобождаются ссылки, можно воспользоваться функцией sys.getrefcount и функциями модуля gc. Но в этом случае нужно определить, какие переменные следует контролировать, ибо все - обычно нереально.

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

Место поиска проблемы сузилось:

Так вот через каждые 0.5 секунды вызывается функция отрисовки буфера [code:python] def redraw(self): self.sc.delete('line') dx=(1)*self.zoom_x self.param.mutex.acquire() now=(time()-self.dt) for i in self.param.buf: dt=(now-i[0]) if ((dt>=0) and (dt<=self.sec_for_draw)): dt=self.freq*(self.sec_for_draw-dt)*self.zoom_x self.sc.create_line(dt, (self.max-self.py)*self.zoom_y, dt+dx,(self.max-i[1])*self.zoom_y, tags=('line',`i[0]`, `i[1]`)) self.py=i[1] self.param.mutex.release() self.sc.resizescrollregion() self.fun=self.after(500, self.redraw) [/code] если заккоментить строчку self.sc.create_line(dt, (self.max-self.py)*self.zoom_y, dt+dx,(self.max-i[1])*self.zoom_y, tags=('line',`i[0]`, `i[1]`)) все нормально, если ее расскоментировать уходит по Мб в 10 минут.

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

> self.sc.create_line(dt, (self.max-self.py)*self.zoom_y, dt+dx,(self.max-i[1])*self.zoom_y, tags=('line',`i[0]`, `i[1]`))

Насколько я понимаю, это Tkinter?

Метод create_line не просто рисует линию (т.е. меняет цвет пикселей), он создаёт объект, которым потом можно управлять, и который, естественно, отъедает память. Если есть возможность, надо удалять ранее нарисованные линии. Сделать это можно методом delete, указав ему тэг или ранее сохранённый id (результат create_line).

Ещё один момент: create_line создаёт ломаную линию, значит можно нарисовать весь график одним вызовом create_line, передав ему кортеж координат.

DKorolkov
()

Посмотри документацию по модулю gc. Там, вроде, что-то есть для отладки memory-leak'ов.

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

>Если есть возможность, надо удалять ранее нарисованные линии. Сделать >это можно методом delete В самом начале функции стоит self.sc.delete('line') =( За идею нарисовать все одним вызовом - спасибо! А вообще, по Tkinter очень мало хорошей документации, или я плохо ищу. sys.refcount() для объектов линий дает какие-то дикие числа, даже в простейшем примере, по всей видимости здесь не подходит? штудирую gc... Спасибо за совет =)

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

Tkinter

> В самом начале функции стоит self.sc.delete('line')

То есть, к линиям привязывается кортеж тегов, а потом вы пытаетесь обратиться по одному из них. Похоже, это не работает.

> А вообще, по Tkinter очень мало хорошей документации, или я плохо ищу.

У меня на диске лежат файлы an-introduction-to-tkinter.pdf и thinking_in_tkinter.zip. Откуда брал, не помню, попробуйте поискать. Можно пройтись по ссылкам с python.ru и python.org.

> sys.refcount() для объектов линий дает какие-то дикие числа, даже в простейшем примере, по всей видимости здесь не подходит?

Результат create_line - целое число, дескриптор, используемый внутри Tkinter. sys.refcount() даёт для него количество ссылок на это целое значение. Этот результат не имеет никакого отношения к линии.

DKorolkov
()
Ответ на: Tkinter от DKorolkov

> То есть, к линиям привязывается кортеж тегов, а потом вы пытаетесь обратиться по одному из них. Похоже, это не работает. Но с холста линии удалаяются... an-introduction-to-tkinter.pdf есть, а вот thinking_in_tkinter надо поискать.

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

Документация

> А вообще, по Tkinter очень мало хорошей документации

Вдогонку: Tkinter - это обвязка для Tk, соответственно, надо смотреть документацию по Tk, она входит в стандартную документацию по TCL.

Правда, здесь есть два момента:

1. Документация по Tk предполагает использование TCL, а не Python/Tkinter.

2. Tkinter не полностью охватывает Tk.

Ну и, соответственно, tkinter.py .

P.S. На этом форуме для перехода на другую строку нужно ставить пустые строки или использовать другой тип форматирования (селектор под полем ввода текста).

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

Работа с одной линией

Ещё одна идея: вместо того, чтобы удалять старые линии и создавать новые,
можно создать одну линию и менять её координаты.

Пример:

from Tkinter import *
import random

def new_line():
	coords = [lid]
	for x in xrange(0,500,5):
		y = random.randint(0, 100)
		coords.extend([x,y])
	cnv.coords(*coords)
	tk.after(10, new_line)

random.seed()
tk = Tk()
cnv = Canvas(tk, bg='White', width=500, height=100)
cnv.pack()
lid = cnv.create_line(0,0,500,100)
tk.after(100, new_line)

tk.mainloop()

DKorolkov
()
Ответ на: Работа с одной линией от DKorolkov

Спасибо, идея интересная. Только мне не подходит ... Так как я отрисовываю, только те данные, которые соответствуют данному моменту времени ( то есть есть буфер - у каждой точки - время снятия), то могут быть разрывы в линиях - если нет данных на это время..., поэтому же, так как каждой линии нужно назначить свой тэг (с временем снятия - нужно для других целей), все линии придется удалять и отрисовывать снова. Замечено, что при увеличении интервала отрисовки (примерно 3-4 секунды) утечка памяти прекращается. Но это слишком медленно для моей задачи. Похоже нет решения... Все-таки Питон и не предназначен дял скоростной работы в реалтайме =(

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