5

In a piece of my code, my script generates a string to copy it in a scrolled text widget. if the size of the string is not so heavy, this process works without any kind of issues, but when the string is heavy, the script can't paste it into the scrolled text widget. when it happens, the script crashes, and an error message appears in the terminal: unable to alloc 27 bytes (it's not an exception event).

before the crash, I got the bytes size of the string via sys.getsizeof function, and it was 230031360 bytes (230 MB).

In these cases, the user can solve the issue by choosing to write the output message in a text file, but what about if the user tries to write a heavy string in the scrolled text widget anyway? In this specific case, I would very like to show a message box to advice the user to write the output in a text file, but how can I understand if the script can write the string in the scrolled text widget or not? what is the bytes limit of a string in Python?

UPDATE:

I wrote an example to show you where the issue occurs. the main window will crash in oround two minutes with an error message in the terminal, unable to alloc 28 bytes:

from tkinter import *
from tkinter import ttk, scrolledtext
import ipaddress

def GiveMeHosts():
    ls = []
    for host in ipaddress.ip_network("10.0.0.0/8").hosts():
        ls.append(str(host))
    return ls

parent = Tk()
parent.geometry("400x350")
parent.title("The window will crash..")

MyWidget=scrolledtext.ScrolledText(parent, wrap=WORD, width=36, height=14, font=("Segoe UI", 9), state="normal")
MyWidget.pack()

parent.update()

# the string "hosts" is too long, and "MyWidget" can't manage it!
hosts = "\n".join(GiveMeHosts())
MyWidget.insert("1.0", hosts) # it makes the script to crash

parent.mainloop()
Raed Ali
  • 549
  • 1
  • 6
  • 22
  • First of all, normally there is virtually no size limit to a string in Python, depending on your systems RAM size of course. Second, `sys.getsizeof(astring)` doesn't give the string size in bytes, but rather the size of the str object (which includes overhead). Unfortunately I couldn't (quickly) find if there are limits to tkinter, and if so, what they are, but it certainly would not surprise me. – Ronald Jun 17 '20 at 16:43
  • Ciao Ronald. Do you know if there is a way to handle the `unable to alloc xxx bytes` error? If I can't to understand what is the memory limit for the scrolled text widget, at least I would like to handle the error and avoid the crash of my script. Is it possibile? – RisoGalloExresso Jun 27 '20 at 00:26
  • Do you have a small piece of code that generates the error? For now, I don't really have a clue though my first thought is that some imported function already handles an error and produces this message. – Ronald Jun 27 '20 at 09:59
  • I just wrote a little example (see my post). what do you think? – RisoGalloExresso Jun 27 '20 at 13:56
  • I ran your code, and while it took quite some time, it did finally put all IP addresses in the scrolled text box. No errors! By the way: `unable to alloc 28 bytes`, isn't that exactly the size of the last two ip-adresses ?!? (`10.255.255.253 10.255.255.254`) – Ronald Jun 27 '20 at 14:14
  • really? it's very weird. I tried my code in another PC (i7, 16 GB), more powerful than mine (i5, 8GB), and I saw the same error but with a different byte size, `unable to alloc 16 bytes`. for your question I'm not sure, teorically an IPv4 address is composed by 32 bits, but considering the points between the numbers probably we have to consider an encoding. if I'm not mistaken in UTF-8 encoding, an ASCII caracter is composed by 1 byte, and the last two IPs are composed by 29 characters (you have to consider the space too). – RisoGalloExresso Jun 27 '20 at 14:41
  • mm.. now I really don't know how to go ahead. do you have some ideas on how to investigate the issue? – RisoGalloExresso Jun 27 '20 at 14:41
  • I was running the program on a i7, 32GB by the way. – Ronald Jun 27 '20 at 14:51
  • UPDATE: I just installed the x64 version of Python (3.9.0) and now the script works without any kind of issue. until now I always used the x32 version. probably the x32 version can't manage enough memory. – RisoGalloExresso Dec 03 '20 at 23:03

1 Answers1

0

I ran your code, and while it took quite some time, it did finally put all IP addresses in the scrolled text box. No errors and no crashes. By the way: unable to alloc 28 bytes, that is exactly the size of the last two ip-adresses ?!? (10.255.255.253 10.255.255.254).

I went one step further. Actually two steps. Tried to run the same code, but multiplied the return value ls *= 5. Still valid results, no crashes. Meanwhile ls has a size of 1790312344 bytes (1.67 GB).

At ls *=10 however, ls now has a size of 2545286976 bytes (2.37 GB), it finally did crash with the following Traceback:

Traceback (most recent call last):
  File "F:\pybin\StackOverflow\so.py", line 28, in <module>
    MyWidget.insert("1.0", hosts) # it makes the script to crash
  File "C:\Program Files\Python36\lib\tkinter\__init__.py", line 3266, in insert
    self.tk.call((self._w, 'insert', index, chars) + args)
OverflowError: string is too long

Altogether it seems that there is indeed a limit, but the limit may very well be system dependent. At least, that is what I conclude from it.

Ronald
  • 2,930
  • 2
  • 7
  • 18