0

Has anyone tried using python-docx on google cloud functions? I am just getting started and can't get a simple code below work:

from docx import Document
document = Document('blank_doc.docx')
document.save('test.docx');

Edit 1:

Here's the log for above snippet:

2021-02-05T15:39:56.658Ztest1w0yivt7dw3gw Traceback (most recent call last): 
File "/env/local/lib/python3.7/site-packages/google/cloud/functions/worker_v2.py", 
line 402, in run_http_function result = _function_handler.invoke_user_function(flask.request) 
File "/env/local/lib/python3.7/site-packages/google/cloud/functions/worker_v2.py", 
line 268, in invoke_user_function return call_user_function(request_or_event) 
File "/env/local/lib/python3.7/site-packages/google/cloud/functions/worker_v2.py", 
line 261, in call_user_function return self._user_function(request_or_event) 
File "/user_code/main.py", 
line 6, in test1 document.save('document.docx') 
File "/env/local/lib/python3.7/site-packages/docx/document.py", 
line 135, in save self._part.save(path_or_stream) 
File "/env/local/lib/python3.7/site-packages/docx/parts/document.py", 
line 111, in save self.package.save(path_or_stream) 
File "/env/local/lib/python3.7/site-packages/docx/opc/package.py", 
line 172, in save PackageWriter.write(pkg_file, self.rels, self.parts) 
File "/env/local/lib/python3.7/site-packages/docx/opc/pkgwriter.py", 
line 32, in write phys_writer = PhysPkgWriter(pkg_file) 
File "/env/local/lib/python3.7/site-packages/docx/opc/phys_pkg.py", 
line 141, in __init__ self._zipf = ZipFile(pkg_file, 'w', compression=ZIP_DEFLATED) 
File "/opt/python3.7/lib/python3.7/zipfile.py", 
line 1240, in __init__ self.fp = io.open(file, filemode) OSError: [Errno 30] Read-only file system: 'document.docx'

Traceback (most recent call last): File "/env/local/lib/python3.7/site-packages/google/cloud/functions/worker_v2.py", 
line 402, in run_http_function result = _function_handler.invoke_user_function(flask.request) 
File "/env/local/lib/python3.7/site-packages/google/cloud/functions/worker_v2.py", 
line 268, in invoke_user_function return call_user_function(request_or_event) 
File "/env/local/lib/python3.7/site-packages/google/cloud/functions/worker_v2.py", 
line 261, in call_user_function return self._user_function(request_or_event) 
File "/user_code/main.py", line 6, in test1 document.save('document.docx')
File "/env/local/lib/python3.7/site-packages/docx/document.py", 
line 135, in save self._part.save(path_or_stream) 
File "/env/local/lib/python3.7/site-packages/docx/parts/document.py", 
line 111, in save self.package.save(path_or_stream) 
File "/env/local/lib/python3.7/site-packages/docx/opc/package.py", 
line 172, in save PackageWriter.write(pkg_file, self.rels, self.parts) 
File "/env/local/lib/python3.7/site-packages/docx/opc/pkgwriter.py", 
line 32, in write phys_writer = PhysPkgWriter(pkg_file) 
File "/env/local/lib/python3.7/site-packages/docx/opc/phys_pkg.py", 
line 141, in __init__ self._zipf = ZipFile(pkg_file, 'w', compression=ZIP_DEFLATED) 
File "/opt/python3.7/lib/python3.7/zipfile.py", 
line 1240, in __init__ self.fp = io.open(file, filemode) OSError: [Errno 30] Read-only file system: 'document.docx'

I thought this has something to do with the bucket storage thing and tried below but can't seem to get it to work. Appreciate help

from google.cloud import storage
from docx import Document   
client = storage.Client()
import io

def test(request):
    file_stream = io.BytesIO()

    BUCKET = 'out_bucket'
    document = Document('blank_doc.docx')
    bucket = client.get_bucket(BUCKET)
    document.save(file_stream)
    file_stream = file_stream.encode('utf-8')
    newblob = bucket.blob(file_stream)
    newblob.upload_from_file('document.docx')

Edit 2:

Sorry, here is the log for snippet above:

2021-02-05T15:30:53.665Ztest18s7xo9gksz2 Traceback (most recent call last): 
File "/env/local/lib/python3.7/site-packages/google/cloud/functions/worker_v2.py", 
line 402, in run_http_function result = _function_handler.invoke_user_function(flask.request) 
File "/env/local/lib/python3.7/site-packages/google/cloud/functions/worker_v2.py", 
line 268, in invoke_user_function return call_user_function(request_or_event) 
File "/env/local/lib/python3.7/site-packages/google/cloud/functions/worker_v2.py", 
line 261, in call_user_function return self._user_function(request_or_event) 
File "/user_code/main.py", 
line 13, in test file_stream = file_stream.encode('utf-8') AttributeError: 
'_io.BytesIO' object has no attribute 'encode'


Traceback (most recent call last): 
File "/env/local/lib/python3.7/site-packages/google/cloud/functions/worker_v2.py", 
line 402, in run_http_function result = _function_handler.invoke_user_function(flask.request) 
File "/env/local/lib/python3.7/site-packages/google/cloud/functions/worker_v2.py", 
line 268, in invoke_user_function return call_user_function(request_or_event) 
File "/env/local/lib/python3.7/site-packages/google/cloud/functions/worker_v2.py", 
line 261, in call_user_function return self._user_function(request_or_event) 
File "/user_code/main.py", 
line 13, in test file_stream = file_stream.encode('utf-8') AttributeError: 
'_io.BytesIO' object has no attribute 'encode'
Kevin Quinzel
  • 1,430
  • 1
  • 13
  • 23
Hari
  • 3
  • 3
  • You should post the error that you are getting. – Shyrtle Feb 05 '21 at 15:18
  • Since I knew I was a noob, I thought my code was obviously incorrect and didn't add any log in the first place. Added now, thanks for your time. – Hari Feb 05 '21 at 15:43
  • The key part of the traceback appears to be "Read-only filesystem". I expect if you comment out the `.save()` line it will not raise an error. You need somewhere to save the result, or you can save it to a BytesIO "in-memory" file and return the contents of that via an HTTP response body or something. Next time format the traceback to one part per line. Otherwise you're asking readers to do more work than they're likely to do to help you. – scanny Feb 05 '21 at 17:20

1 Answers1

0

On Cloud Functions the only path where you can write documents is on /tmp as mentioned here, so I rewrote the Cloud Function hello_world as:

from docx import Document

def hello_world(request):

    document = Document()
    document.save('/tmp/test.docx');

    request_json = request.get_json()
    if request.args and 'message' in request.args:
        return request.args.get('message')
    elif request_json and 'message' in request_json:
        return request_json['message']
    else:
        return f'Hello World!'

And in the requirements.txt file added the next line:

python-docx
Emmanuel
  • 1,436
  • 1
  • 11
  • 17
  • 1
    Thanks a lot for that answer. It works, I am now out to figure out how to get that data into an output bucket – Hari Feb 27 '21 at 14:08
  • Maybe this [information](https://stackoverflow.com/questions/59799941/writing-a-new-file-to-a-google-cloud-storage-bucket-from-a-google-cloud-function) can help, however if you have troubles while trying to do so, open a new question and I can help you with that – Emmanuel Mar 01 '21 at 15:29