【问题标题】:Has anyone been able to use poppler new_from_data in python?有没有人能够在 python 中使用 poppler new_from_data ?
【发布时间】:2017-03-11 12:45:22
【问题描述】:

使用 Python3 和 Poppler,我可以毫无问题地使用 new_from_file 加载文件,但 new_from_data 是有问题的。这是显然是一个简单测试的代码,因为从文件中读取然后使用 new_from_data 没有意义,因为 new_from_file 可以完美运行,但我无法在此处发布生成 pdf 文件的完整代码。

from gi.repository import Poppler, Gtk

def draw(widget, cr):
        # set background.
        cr.set_source_rgb(0.7, 0.6, 0.5)
        cr.paint()

        # set page background
        cr.set_source_rgb(1, 1, 1)
        cr.rectangle(0,0,800,400)

        cr.fill()
        page.render(cr)

filepath = "d:/Mes Documents/A5.pdf" 
f11 = open(filepath, "r", encoding = "cp850")
data1 = f11.read()
f11.close()

document = Poppler.Document.new_from_data(data1, len(data1),  None)
page = document.get_page(0)
print (document.get_n_pages())


window = Gtk.Window(title="Hello World")
window.connect("delete-event", Gtk.main_quit)
window.connect("draw", draw)
window.set_app_paintable(True)

window.show_all()
Gtk.main()

可能会发生四种不同的情况:

  • 使用非常简单的 pdf(Pdf 参考 13 中的“Hello world”示例),它就可以工作。
  • 用普通文件,可能不会出错,但是get_n_pages返回0,get_page(0)返回None
  • 或者我可能会得到一个错误:GLib.Error: poppler-quark: PDF document is modified (4)
  • 或者程序崩溃

我想知道问题是否可能出在编码参数上,但是我尝试了所有我想到的方法,但没有结果。 我尝试使用“rb”,然后将字节数组转换为字符串:

data1 = "".join(map(data1))

没有结果。

在 Google 上搜索从未返回有效示例

【问题讨论】:

    标签: python pdf poppler


    【解决方案1】:

    我遇到了同样的问题,使用 Gio.MemoryInputStream 解决了它。 不是很优雅,但它确实有效......

    from gi.repository import Poppler, Gtk, Gio
    
    def draw(widget, cr):
            # set background.
            cr.set_source_rgb(0.7, 0.6, 0.5)
            cr.paint()
    
            # set page background
            cr.set_source_rgb(1, 1, 1)
            cr.rectangle(0,0,800,400)
    
            cr.fill()
            page.render(cr)
    
    filepath = "d:/Mes Documents/A5.pdf" 
    with open(filepath, "rb") as f11:
        input_stream = Gio.MemoryInputStream.new_from_data(f11.read())
        # Take care that you need to call .close() on the Gio.MemoryInputStream once you're done with your pdf document.
    
    document = Poppler.Document.new_from_stream(input_stream, -1, None, None)
    page = document.get_page(0)
    print (document.get_n_pages())
    
    
    window = Gtk.Window(title="Hello World")
    window.connect("delete-event", Gtk.main_quit)
    window.connect("draw", draw)
    window.set_app_paintable(True)
    
    window.show_all()
    Gtk.main()
    

    【讨论】:

    • 谢谢,@Trap,它工作正常,但有一点:在 Gio.MemoryInputStream 上调用 .close() 不会释放内存,del 也不会。由于我使用此代码查看 Pdf 页面,因此查看的每个页面都会增加内存使用量,并且可能以 GigaBytes 结尾。
    • 这很奇怪,文档对 close() 的目的非常明确。实际上,如果我理解正确的文档,您甚至不需要调用它,因为一旦流对象被垃圾收集,就应该释放流的资源。 lazka.github.io/pgi-docs/#Gio-2.0/classes/…
    • 我在一个新问题中发布了我的测试代码:stackoverflow.com/questions/45838863/…。答案解释说这是一个错误,并建议使用 new_from_bytes 而不是 new_from_data 遭受错误的影响。经过测试,它可以工作。
    【解决方案2】:

    如果您将文件读取为二进制"rb" 并且没有编码,则它可以工作。我还需要删除数据长度以修复 TypeError: Poppler.Document.new_from_data() takes exactly 2 arguments (3 given)(在 poppler 版本中可能不同)。

    #!/bin/python3
    from gi.repository import Poppler, Gtk
    
    def draw(widget, cr):
            # set background.
            cr.set_source_rgb(0.7, 0.6, 0.5)
            cr.paint()
    
            # set page background
            cr.set_source_rgb(1, 1, 1)
            cr.rectangle(0,0,800,400)
    
            cr.fill()
            page.render(cr)
    
    filepath = "/home/da/test.pdf"
    f11 = open(filepath, "rb")
    data1 = f11.read()
    f11.close()
    
    document = Poppler.Document.new_from_data(data1, None)
    page = document.get_page(0)
    print (document.get_n_pages())
    
    
    window = Gtk.Window(title="Hello World")
    window.connect("delete-event", Gtk.main_quit)
    window.connect("draw", draw)
    window.set_app_paintable(True)
    
    window.show_all()
    Gtk.main()
    

    在 Fedora Linux 上使用 poppler 0.84.0 和 Python 3.8.5 进行测试。

    【讨论】:

    • 当然它取决于 poppler 版本。在唯一可用于 Windows 的旧版本中,我收到错误消息:TypeError:必须是字符串,而不是字节。 Gio.MemoryInputStream 的解决方案效果很好。
    • 已添加版本。
    猜你喜欢
    • 2011-11-03
    • 2012-01-02
    • 1970-01-01
    • 2020-04-06
    • 1970-01-01
    • 1970-01-01
    • 2018-08-14
    • 1970-01-01
    相关资源
    最近更新 更多