6

Python 3 替换StringIO.StringIOio.StringIO. 我已经能够使用前者成功保存演示文稿,但它似乎不适用于后者。

from pptx import Presentation
from io import StringIO

presentation = Presentation('presentation.pptx')
output = StringIO()
presentation.save(output)

上面的代码产生:

Traceback (most recent call last): File "<stdin>", line 1, in <module> File "C:\Users\mgplante\AppData\Local\Continuum\Anaconda2\envs\ppt_gen\lib\site-packages\pptx\presentation.py", line 46, in save self.part.save(file) File "C:\Users\mgplante\AppData\Local\Continuum\Anaconda2\envs\ppt_gen\lib\site-packages\pptx\parts\presentation.py", line 118, in save self.package.save(path_or_stream) File "C:\Users\mgplante\AppData\Local\Continuum\Anaconda2\envs\ppt_gen\lib\site-packages\pptx\opc\package.py", line 166, in save PackageWriter.write(pkg_file, self.rels, self.parts) File "C:\Users\mgplante\AppData\Local\Continuum\Anaconda2\envs\ppt_gen\lib\site-packages\pptx\opc\pkgwriter.py", line 33, in write PackageWriter._write_content_types_stream(phys_writer, parts) File "C:\Users\mgplante\AppData\Local\Continuum\Anaconda2\envs\ppt_gen\lib\site-packages\pptx\opc\pkgwriter.py", line 47, in _write_content_types_stream phys_writer.write(CONTENT_TYPES_URI, content_types_blob) File "C:\Users\mgplante\AppData\Local\Continuum\Anaconda2\envs\ppt_gen\lib\site-packages\pptx\opc\phys_pkg.py", line 156, in write self._zipf.writestr(pack_uri.membername, blob) File "C:\Users\mgplante\AppData\Local\Continuum\Anaconda2\envs\ppt_gen\lib\zipfile.py", line 1645, in writestr with self.open(zinfo, mode='w') as dest: File "C:\Users\mgplante\AppData\Local\Continuum\Anaconda2\envs\ppt_gen\lib\zipfile.py", line 1349, in open return self._open_to_write(zinfo, force_zip64=force_zip64) File "C:\Users\mgplante\AppData\Local\Continuum\Anaconda2\envs\ppt_gen\lib\zipfile.py", line 1462, in _open_to_write self.fp.write(zinfo.FileHeader(zip64)) TypeError: string argument expected, got 'bytes'

有没有办法将演示文稿保存到 Python 3 中的类似文件的对象,或者我将不得不为这个项目使用 Python 2?

4

3 回答 3

5

怎么样BytesIO()

from pptx import Presentation
from io import BytesIO

presentation = Presentation('presentation.pptx')
output = BytesIO()
presentation.save(output)
output.seek(0)
# from here do what you like with output, e.g. pass it to something expecting bytes with output.read()

这至少消除了错误。

于 2017-10-27T16:35:53.870 回答
3

Hannu 的回答非常正确,并且正是用于在测试套件中验证此行为的代码python-pptx

stream = BytesIO()
presentation.save(stream)

https://github.com/scanny/python-pptx/blob/master/features/steps/presentation.py#L105

如果该代码给你一个空白的演示文稿,那么其他事情正在发生。我会重现该行为,使其稳定且可重复,然后提出“为什么我得到一个空白演示文稿?”的问题。在另一个 SO 问题中,与它一起发布为您提供该行为的完整最低代码。

这是我第二次听说这样的事情,这让我怀疑实际上是在幕后发生了一些系统性的事情来产生这种行为。但与此同时,由于尝试保存到流的部分失败,您极不可能最终得到一个完整的演示文稿,只是没有幻灯片。

可能导致这种情况的常见情况是保存新打开的默认演示文稿,例如:

prs = Presentation()
output = BytesIO()
prs.save(output)

这当然不是你可能会故意做的事情,但很容易意外地做到,所以我想我会提到。

如果你能帮助我们重复你的结果,我们会弄明白的:)

于 2017-10-27T17:46:11.907 回答
1

在开发类似 CGI 的演示文稿时,我遇到了同样的问题。我的 pptx 应该作为文件发送给用户。您可以使用 BytesIO 而不是 StringIO 将 pptx 作为文件发送

qs = cgi.FieldStorage()
link = qs.getfirst('link', 'default_link_for_debug')

...
...

target_stream = BytesIO()
prs.save(target_stream)
target_stream.seek(0) # important!

length = target_stream.getbuffer().nbytes
buffer = target_stream.getbuffer()
#buffer = target_stream.read() # it also works

if 'HTTP_HOST' in os.environ:
    sys.stdout.buffer.write(b'Content-Type: application/vnd.openxmlformats-officedocument.presentationml.presentation\r\n')
    sys.stdout.buffer.write('Content-Disposition: attachment; filename="offer-{0}.pptx"\r\n'.format(link).encode('ascii'))
    sys.stdout.buffer.write('Content-Length: {0}\r\n'.format(length).encode('ascii'))
    sys.stdout.buffer.write(b'Pragma: no-cache\r\n')
    sys.stdout.buffer.write(b'\r\n')
    sys.stdout.buffer.write(buffer)

else: # for debug
    with open("offer-{0}.pptx".format(link),'wb') as out: 
        out.write(buffer) 
于 2018-11-23T01:06:08.517 回答