Python 3将StringIO.StringIO
替换为io.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?
答案 0 :(得分:4)
BytesIO()
怎么样?
from pptx import Presentation
from io import BytesIO
presentation = Presentation('presentation.pptx')
output = BytesIO()
presentation.save(output)
这至少消除了错误。
答案 1 :(得分:2)
Hannu的答案非常正确,而且恰恰是用于在python-pptx
的测试套件中验证此行为的代码:
stream = BytesIO()
presentation.save(stream)
https://github.com/scanny/python-pptx/blob/master/features/steps/presentation.py#L105
如果该代码给你一个空白的演示文稿,那么其他的东西正在发生。我会重现这种行为,让它保持稳定和可重复,然后问问题效果&#34;为什么我会得到一个空白的演示文稿?&#34;在另一个SO问题中,用它发布给你这种行为的完整最小代码。
这是我第二次听说过这样的事情,这让我怀疑实际上有一些半途而废的系统事件会产生这种行为。但与此同时,你最不可能完成一个完全有效的演示文稿,只是没有幻灯片,因为尝试保存到流中是部分失败。
导致这种情况的常见情况是保存新打开的默认演示文稿,例如:
prs = Presentation()
output = BytesIO()
prs.save(output)
这当然不是你可能会故意做的事情,但很容易偶然发生,所以我想我会提。
如果您可以帮助我们重复您的结果,我们会弄明白:)
答案 2 :(得分: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)