David Talkin <dtal...@gmail.com> added the comment:

Attached please find a Python script that demonstrates the bug.

David

On Tue, Sep 25, 2018 at 2:55 AM Karthikeyan Singaravelan <
rep...@bugs.python.org> wrote:

>
> Karthikeyan Singaravelan <tir.kar...@gmail.com> added the comment:
>
> Thanks for the report David. Feel free to attach reproducible script if
> any that might trigger this. I am adding Serhiy who might have a better
> understanding of this. Relevant issue where _createbytearray was added :
> issue21580 .
>
> ----------
> nosy: +serhiy.storchaka, xtreak
>
> _______________________________________
> Python tracker <rep...@bugs.python.org>
> <https://bugs.python.org/issue34794>
> _______________________________________
>

----------
Added file: https://bugs.python.org/file47821/leak_demo.py

_______________________________________
Python tracker <rep...@bugs.python.org>
<https://bugs.python.org/issue34794>
_______________________________________
#!/usr/bin/python

#
#
# Copyright 2018 David Talkin.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

"""This demonstrates that Tkinter.PhotoImage leaks memory with each data update.

To see the leak, run this as a main program and watch memory usage on
the system monitor.  The leak occurs in LeakDemo.ShowImage.

"""
import sys
import math
import Tkinter as tk
import numpy as np

__author__ = 'dtal...@gmail.com (David Talkin)'


class LeakDemo(object):
    """Demonstrates the memory leak due to calls to TkApp._createbytearray.
    """
    def __init__(self, height=600, width=1000):
        self.height = height
        self.width = width
        self.root = tk.Tk()
        self.frame = tk.Frame(self.root)
        self.frame.pack()
        self.canvas = tk.Canvas(self.frame, height=self.height,
                                width=self.width)
        self.canvas.pack(side=tk.TOP, expand=tk.YES, fill=tk.BOTH)
        self.image = None
        self.photo = None
        self.phase = 0.0

    def MakeSignals(self):
        """Create signals that will modulate the red, blue and green
        intensities in the image.  Return them as a three-element list of
        numpy arrays.
        """
        freqs = [5.0, 7.0, 9.0]
        sigs = []
        amp = 128.0
        for freq in freqs:
            arg = math.pi * 2.0 * freq / self.width
            ara = np.zeros(self.width, dtype=np.float32)
            for i in range(self.width):
                ara[i] = amp * math.sin(self.phase + (arg * i))
            sigs.append(ara)
        self.phase += math.pi / 100.0
        return sigs

    def CreateImage(self, sigs):
        """Accept a list of three arrays that represent the red, blue and
        green intensities across the canvas.  Return a PPN-format image to be
        displayed.
        """
        odata = np.array(sigs).transpose().flatten()
        amax = 128
        if len(odata) > self.width * 3:
            odata = odata[:self.width * 3]
        head = 'P6\n%d %d\n%d\n' % (len(odata)/3, self.height, amax)
        bdata = head + (np.array([min(amax, max(0, (128 + v) / 2))
                                  for v in odata],
                                 dtype=np.uint8).tostring() * (self.height))
        return bdata

    def ShowImage(self, image_data):
        """The leak happens here when PhotoImage is instantiated an after each
        call to configure.
        """
        if not self.photo:
            self.photo = tk.PhotoImage(master=self.root, data=image_data,
                                       format='PPM')
            self.image = self.canvas.create_image((1 + self.width) / 2,
                                                  (1 + self.height) / 2,
                                                  image=self.photo)
        else:
            self.photo.configure(data=image_data)

    def RunDemo(self):
        sigs = self.MakeSignals()
        image = self.CreateImage(sigs)
        self.ShowImage(image)
        self.root.after(33, self.RunDemo)  # About 30 frames/second.


def Main(unused_args):
    demo = LeakDemo()
    demo.RunDemo()
    tk.mainloop()


if __name__ == '__main__':
    Main(sys.argv)
_______________________________________________
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to