0

I have a function that prints text to the console. Below is a version of what the code looks like (it's actually a lot of lines of a story, so I'm summarizing it.) My question is - is there another function I can write to take all_text() and generate a docx file with the it? I've managed to create a .txt file, but I would ideally like to create something with formatting options.

from docx import Document


document = Document()

def all_text():
     print("Line1\nLine2\nLine3")

document.add_paragraph(all_text())
document.save("demo.docx")
Unicorn_tech
  • 207
  • 1
  • 4
  • 18
  • 2
    https://python-docx.readthedocs.io/en/latest/ – Green Cloak Guy Feb 11 '20 at 13:00
  • @GreenCloakGuy I am familiar with this doc, the problem I have is that my function is no longer regarded as a string, so I couldn't get this to work. If I can get around that issue, then the above link is exactly what I would like to use. – Unicorn_tech Feb 11 '20 at 13:12
  • Why isn't your function regarded as a string anymore? – Jamie Feb 11 '20 at 13:58
  • @Jamie I've just updated the question with the fuller code. It generates an empty tile, I'm assuming because the function is not a string. – Unicorn_tech Feb 11 '20 at 14:28
  • 2
    Your function prints a string but doesn't look like it returns anything. `document.add_paragraph(...)` will expect an input. If your function doesn't `return` anything - then nothing will be added. Take a look at [this answer](https://stackoverflow.com/a/7129293/4590710). Hopefully it makes it clear that the function needs to pass back a value to the _caller_. – Jamie Feb 11 '20 at 14:32
  • _my function is no longer regarded as a string_ ..... _because the function is not a string_ It's a function, it will never be a string. – AMC Feb 11 '20 at 20:36
  • I'm voting to close this, it's simply a matter of understanding functions and returning values, there have been plenty like it, and I can't see it being of any use in the future. – AMC Feb 11 '20 at 20:36

1 Answers1

0

Document.add_paragraph() expects a string. Your all_text() function is not returning a string, but writing to sys.stdout (which is by default redirected to your console) and (implicitely) returning None.

The clean solution is of course to change your all_text() function so that it returns a string instead of writing to sys.stdout ie

def all_text():
    return "Line1\nLine2\nLine3"

If your real function actually does a lot of printing in different places and/or call functions which themselves print to stdout etc, making the "clean solution" impractical or too expensive, you can also hack around by redirecting sys.stdout to a StringIO and sending the collected values to add_paragraph, ie:

import sys
try:
   from io import StringIO # py3
except ImportError:
   from cStringIO import StringIO

def all_text():
     print("Line1\nLine2\nLine3")


def get_all_text():
    sys.stdout = buffer = StringIO
    try:
        all_text()
        return  buffer.getvalue()
    finally:
        sys.stdout = sys.__stdout__

document.add_paragraph(get_all_text())
bruno desthuilliers
  • 75,974
  • 6
  • 88
  • 118
  • Thank you . I am interested in the clean function, so I appreciate the suggestion. It gets me more where I need to be. I couldn't simply do return "Line123", I had to set a variable to equal the string, and then return the variable. – Unicorn_tech Feb 11 '20 at 18:08