如何从 Python 中的 GLib.GString 获取原始字节?
How to get raw bytes from GLib.GString in Python?
我有一个通过 GObject 自检(Python 2.7 和 PyGObject 3.14)使用 GTK3 用 Python 编写的应用程序。我正在尝试使用 WebKit 加载网页并访问它加载的所有资源的内容。我可以通过连接到我用来加载页面的 WebKitWebView 对象的 resource-load-finished 信号来完成此操作。
在我的信号处理程序中,我使用 web_resource 参数中的 WebKitWebResource 对象来访问加载的数据。当 get_data() 返回的 GLib.GString 不包含 NULL 字节时,一切正常,我可以使用 data.str 访问我需要的内容。然而,当数据确实包含 NULL 字节时,这种情况通常是加载资源的 MIME 类型是图像时,data.len 是正确的,但 data.str 只包含第一个 NULL 字节之前的数据.我可以通过调用 data.free_to_bytes() returns 一个 GLib.GBytes 实例来访问原始字节,但是当信号处理程序 returns 应用程序出现段错误时。我正在尝试访问已加载资源中的所有数据。
我希望以下代码有助于说明问题。
from gi.repository import Gtk
from gi.repository import WebKit
def signal_resource_load_finished(webview, frame, resource):
gstring = resource.get_data()
print(resource.get_mime_type())
desired_len = gstring.len
# gstring.str is missing data because it returns the data up to the first NULL byte
assert(gstring.str == desired_len) # this assertion fails
# calling this causes a segfault after the handler returns, but the data is accessible from gbytes.get_data()
#gbytes = gstring.free_to_bytes()
#assert(len(gbytes.get_data()) == desired_len) # this assertion succeeds before the segfault
return
webview = WebKit.WebView()
webview.connect('resource-load-finished', signal_resource_load_finished)
webview.connect('load-finished', Gtk.main_quit)
# lol cat for demo purposes of a resource containing NULL bytes (mime type: image/png)
webview.load_uri('http://images5.fanpop.com/image/photos/30600000/-Magical-Kitty-lol-cats-30656645-1280-800.png')
Gtk.main()
您不想使用 free_to_bytes
,因为这不仅会为您提供所需的字节,而且还会在 Python 不知情的情况下从内存中释放字符串 - 正如您发现,使您的程序崩溃。不幸的是,没有相应的 get_bytes
方法,因为 GLib.String
并非真正设计用于保存二进制数据。
事实上,我认为 WebKit API 中的一个错误是资源负载仅作为 GLib.String
可用。他们似乎已经纠正了 WebKit2 中的这个错误:http://webkitgtk.org/reference/webkit2gtk/stable/WebKitWebResource.html
如果可以,请考虑切换到 WebKit2 (from gi.repository import WebKit2
)。
我有一个通过 GObject 自检(Python 2.7 和 PyGObject 3.14)使用 GTK3 用 Python 编写的应用程序。我正在尝试使用 WebKit 加载网页并访问它加载的所有资源的内容。我可以通过连接到我用来加载页面的 WebKitWebView 对象的 resource-load-finished 信号来完成此操作。
在我的信号处理程序中,我使用 web_resource 参数中的 WebKitWebResource 对象来访问加载的数据。当 get_data() 返回的 GLib.GString 不包含 NULL 字节时,一切正常,我可以使用 data.str 访问我需要的内容。然而,当数据确实包含 NULL 字节时,这种情况通常是加载资源的 MIME 类型是图像时,data.len 是正确的,但 data.str 只包含第一个 NULL 字节之前的数据.我可以通过调用 data.free_to_bytes() returns 一个 GLib.GBytes 实例来访问原始字节,但是当信号处理程序 returns 应用程序出现段错误时。我正在尝试访问已加载资源中的所有数据。
我希望以下代码有助于说明问题。
from gi.repository import Gtk
from gi.repository import WebKit
def signal_resource_load_finished(webview, frame, resource):
gstring = resource.get_data()
print(resource.get_mime_type())
desired_len = gstring.len
# gstring.str is missing data because it returns the data up to the first NULL byte
assert(gstring.str == desired_len) # this assertion fails
# calling this causes a segfault after the handler returns, but the data is accessible from gbytes.get_data()
#gbytes = gstring.free_to_bytes()
#assert(len(gbytes.get_data()) == desired_len) # this assertion succeeds before the segfault
return
webview = WebKit.WebView()
webview.connect('resource-load-finished', signal_resource_load_finished)
webview.connect('load-finished', Gtk.main_quit)
# lol cat for demo purposes of a resource containing NULL bytes (mime type: image/png)
webview.load_uri('http://images5.fanpop.com/image/photos/30600000/-Magical-Kitty-lol-cats-30656645-1280-800.png')
Gtk.main()
您不想使用 free_to_bytes
,因为这不仅会为您提供所需的字节,而且还会在 Python 不知情的情况下从内存中释放字符串 - 正如您发现,使您的程序崩溃。不幸的是,没有相应的 get_bytes
方法,因为 GLib.String
并非真正设计用于保存二进制数据。
事实上,我认为 WebKit API 中的一个错误是资源负载仅作为 GLib.String
可用。他们似乎已经纠正了 WebKit2 中的这个错误:http://webkitgtk.org/reference/webkit2gtk/stable/WebKitWebResource.html
如果可以,请考虑切换到 WebKit2 (from gi.repository import WebKit2
)。