Python-docx: TypeError: string argument expected, got 'bytes'

Created on 21 Sep 2018  路  3Comments  路  Source: python-openxml/python-docx

Hi,
document.save() receives a file path or stream, right? What am I doing wrong?

This a flask application....
`@app.route('/doc')
def index():

document = Document()
document.add_heading('Document Title', 0)
document.add_paragraph('Some text')
buffer = io.StringIO()
document.save(buffer)
buffer.seek(0)
return Response(buffer, mimetype='application/vnd.openxmlformats-officedocument.wordprocessingml.document')`

ERROR:

  • Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
    [2018-09-20 19:53:58,458] ERROR in app: Exception on /doc [GET]
    Traceback (most recent call last):
    File "C:\Users\chsdo\PycharmProjects\untitled\venv\lib\site-packages\flask\app.py", line 2292, in wsgi_app
    response = self.full_dispatch_request()
    File "C:\Users\chsdo\PycharmProjects\untitled\venv\lib\site-packages\flask\app.py", line 1815, in full_dispatch_request
    rv = self.handle_user_exception(e)
    File "C:\Users\chsdo\PycharmProjects\untitled\venv\lib\site-packages\flask\app.py", line 1718, in handle_user_exception
    reraise(exc_type, exc_value, tb)
    File "C:\Users\chsdo\PycharmProjects\untitled\venv\lib\site-packages\flask_compat.py", line 35, in reraise
    raise value
    File "C:\Users\chsdo\PycharmProjects\untitled\venv\lib\site-packages\flask\app.py", line 1813, in full_dispatch_request
    rv = self.dispatch_request()
    File "C:\Users\chsdo\PycharmProjects\untitled\venv\lib\site-packages\flask\app.py", line 1799, in dispatch_request
    return self.view_functionsrule.endpoint
    File "C:\Users\chsdo\PycharmProjects\untitled\app.py", line 26, in index
    document.save(buffer)
    File "C:\Users\chsdo\PycharmProjects\untitled\venv\lib\site-packages\docx\document.py", line 142, in save
    self._part.save(path_or_stream)
    File "C:\Users\chsdo\PycharmProjects\untitled\venv\lib\site-packages\docx\parts\document.py", line 130, in save
    self.package.save(path_or_stream)
    File "C:\Users\chsdo\PycharmProjects\untitled\venv\lib\site-packages\docx\opc\package.py", line 160, in save
    PackageWriter.write(pkg_file, self.rels, self.parts)
    File "C:\Users\chsdo\PycharmProjects\untitled\venv\lib\site-packages\docx\opc\pkgwriter.py", line 33, in write
    PackageWriter._write_content_types_stream(phys_writer, parts)
    File "C:\Users\chsdo\PycharmProjects\untitled\venv\lib\site-packages\docx\opc\pkgwriter.py", line 45, in _write_content_types_stream
    phys_writer.write(CONTENT_TYPES_URI, cti.blob)
    File "C:\Users\chsdo\PycharmProjects\untitled\venv\lib\site-packages\docx\opc\phys_pkg.py", line 155, in write
    self._zipf.writestr(pack_uri.membername, blob)
    File "C:\Users\chsdo\AppData\Local\Programs\Python\Python37\lib\zipfile.py", line 1762, in writestr
    with self.open(zinfo, mode='w') as dest:
    File "C:\Users\chsdo\AppData\Local\Programs\Python\Python37\lib\zipfile.py", line 1448, in open
    return self._open_to_write(zinfo, force_zip64=force_zip64)
    File "C:\Users\chsdo\AppData\Local\Programs\Python\Python37\lib\zipfile.py", line 1561, in _open_to_write
    self.fp.write(zinfo.FileHeader(zip64))
    TypeError: string argument expected, got 'bytes'
    Exception ignored in:
    Traceback (most recent call last):
    File "C:\Users\chsdo\AppData\Local\Programs\Python\Python37\lib\zipfile.py", line 1767, in __del__
    self.close()
    File "C:\Users\chsdo\AppData\Local\Programs\Python\Python37\lib\zipfile.py", line 1785, in close
    self._write_end_record()
    File "C:\Users\chsdo\AppData\Local\Programs\Python\Python37\lib\zipfile.py", line 1888, in _write_end_record
    self.fp.write(endrec)
    TypeError: string argument expected, got 'bytes'
    127.0.0.1 - - [20/Sep/2018 19:53:58] "GET /doc HTTP/1.1" 500 -

Most helpful comment

Pretty sure you want io.BytesIO rather that io.StringIO because the saved file is binary, not unicode. Also, I'm not sure what Flask is looking for as the first parameter of the Response() call, but I expect it's bytes rather than a file-like object. You can get bytes from an io.BytesIO object with buffer.getvalue(), and there's no need to .seek(0) before that call.

All 3 comments

Pretty sure you want io.BytesIO rather that io.StringIO because the saved file is binary, not unicode. Also, I'm not sure what Flask is looking for as the first parameter of the Response() call, but I expect it's bytes rather than a file-like object. You can get bytes from an io.BytesIO object with buffer.getvalue(), and there's no need to .seek(0) before that call.

@scanny thanks a lot!
I appreciate your help and many thanks for the incredible tool that you are building...
You gave me the solution. My code now works fine...

`
def index():

document = Document()
document.add_paragraph('A plain paragraph having some ')
document.add_heading('Heading, level 1')
document.add_paragraph('Intense quote')
buffer = io.BytesIO()
document.save(buffer)
buffer.seek(0)

return send_file(buffer, as_attachment=True, attachment_filename='report.doc')`

Pretty sure you want io.BytesIO rather that io.StringIO because the saved file is binary, not unicode. Also, I'm not sure what Flask is looking for as the first parameter of the Response() call, but I expect it's bytes rather than a file-like object. You can get bytes from an io.BytesIO object with buffer.getvalue(), and there's no need to .seek(0) before that call.

Thank you so much! help me a lot

Was this page helpful?
0 / 5 - 0 ratings