pythonautomationdocxdata-analysis

How to encapsulate method to print console out to Word


I want to print my summary stats sometimes to console, and also other times to Word.

I don't want my code to be littered with lines calling to Word, because then I'd need to find and comment out like 100 lines each time I just wanted the console output.

I've thought about using a flag variable up at the front and changing it to false when I wanted to print versus not, but that's also a hassle.

The best solution I came up with was to write a separate script that opens a document, writes by calling my first summary stats script, and then closes the document:

import sys
import RunSummaryStats
from docx import Document

filename = "demo.docx"
document = Document()
document.save(filename)
f = open(filename, 'w')
sys.stdout = f

# actually call my summary stats script here: Call RunSummaryStats etc.
print("5")

f.close()

However, when I tried doing the above with python docx, upon opening my docs file I received the error We're sorry, we can't open this document because some parts are missing or invalid. As you can see the code above just printed out one number so it can't be a problem with the data I'm trying to write.

Finally, it needs to go to Word and not other file formats, to format some data tables.

By the way, this is an excerpt of RunSummaryStats. You can see how it's already filled with print lines which are helpful when I'm still exploring the data, and which I don't want to get rid of/replace with adding into a list: enter image description here


Solution

  • The easy thing is to let cStringIO do the work, and separate collecting all your data from writing it into a file. That is:

    import RunSummaryStats
    import sys
    
    # first, collect all your data into a StringIO object
    orig_stdout = sys.stdout
    stat_buffer = cStringIO.StringIO()
    sys.stdout = stat_buffer
    try:
        # actually call my summary stats script here: Call RunSummaryStats etc.
        print("5")
    finally:
        sys.stdout = orig_stdout
    
    # then, write the StringIO object's contents to a Document.
    from docx import Document
    filename = "demo.docx"
    document = Document()
    document.write(add_paragraph(stat_buffer.getvalue()))
    document.save(filename)