Python3 和 Tkinter - 无法分配 27 个字节
Posted
技术标签:
【中文标题】Python3 和 Tkinter - 无法分配 27 个字节【英文标题】:Python3 and Tkinter - Unable to alloc 27 bytes 【发布时间】:2020-10-07 09:41:26 【问题描述】:在我的一段代码中,我的脚本会生成一个字符串以将其复制到一个 scolled 文本小部件中。如果字符串的大小不是那么重,则此过程可以正常工作,但是当字符串很重时,脚本无法将其粘贴到滚动的文本小部件中。发生这种情况时,脚本会崩溃,并且终端中会出现错误消息:unable to alloc 27 bytes
(这不是异常事件)。
在崩溃之前,我通过sys.getsizeof
函数得到了字符串的字节大小,它是230031360字节(230 MB)。
在这些情况下,用户可以解决选择在文本文件中写入输出消息的问题,但是如果用户尝试在 scolled 文本小部件中写入重字符串怎么办?在这种特定情况下,我非常想显示一个消息框来建议用户将输出写入文本文件,但我如何理解脚本是否可以在滚动文本小部件中写入字符串? Python中字符串的字节数限制是多少?
更新:
我写了一个例子来告诉你问题出在哪里。主窗口将在大约两分钟后崩溃,并在终端中显示错误消息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()
【问题讨论】:
首先,通常 Python 中的字符串实际上没有大小限制,当然这取决于您的系统 RAM 大小。其次,sys.getsizeof(astring)
没有给出以字节为单位的字符串大小,而是给出 str 对象的大小(包括开销)。不幸的是,我无法(很快)找到 tkinter 是否有限制,如果有,它们是什么,但这肯定不会让我感到惊讶。
Ciao Ronald。你知道是否有办法处理unable to alloc xxx bytes
错误吗?如果我无法理解滚动文本小部件的内存限制是多少,至少我想处理错误并避免我的脚本崩溃。有可能吗?
你有一小段代码会产生错误吗?现在,虽然我的第一个想法是某些导入的函数已经处理错误并产生此消息,但我并没有真正的线索。
我只是写了一个小例子(见我的帖子)。你怎么看?
我运行了您的代码,虽然花费了相当长的时间,但它最终还是将所有 IP 地址放入了滚动的文本框中。没有错误!顺便说一句:unable to alloc 28 bytes
,这不正是最后两个 IP 地址的大小吗?!? (10.255.255.253 10.255.255.254
)
【参考方案1】:
我运行了您的代码,虽然花费了相当长的时间,但它最终还是将所有 IP 地址放入了滚动的文本框中。没有错误,也没有崩溃。顺便说一句:unable to alloc 28 bytes
,这正是最后两个 IP 地址的大小?!? (10.255.255.253 10.255.255.254)。
我更进一步。其实分两步。尝试运行相同的代码,但乘以返回值ls *= 5
。结果仍然有效,没有崩溃。同时ls
的大小为1790312344 bytes (1.67 GB)
。
然而,在ls *=10
,ls
现在的大小为2545286976 bytes (2.37 GB)
,它最终崩溃并出现以下 Traceback:
Traceback (most recent call last):
File "F:\pybin\***\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
总而言之,似乎确实存在一个限制,但该限制很可能取决于系统。至少,这是我从中得出的结论。
【讨论】:
我真的不明白为什么你有一个异常错误而不是崩溃..我们有不同的行为。你的python版本是什么?我使用 Python 3.8.2 (tags/v3.8.2:7b3ab59, Feb 25 2020, 22:45:29) 我刚刚安装了 Python3 的最新版本,但我遇到了同样的问题.. 我碰巧用的是3.6.4版。 我还在使用 Mac OSX Mojave(4 个 vCPU 和 3 GB RAM)的虚拟机中尝试了该脚本。没有检测到问题,脚本有效.. 那么问题是什么?为什么在我安装了 W10 的 PC 中,脚本不起作用?unable to alloc xxx bytes
是什么意思?
在 MAC OSX 中我有最新版本的 Python (3.8.3)。以上是关于Python3 和 Tkinter - 无法分配 27 个字节的主要内容,如果未能解决你的问题,请参考以下文章
Python3.5、Win32gui、Tkinter。我无法从屏幕获取 Pixel