如何封装将控制台打印到 Word 的方法

How to encapsulate method to print console out to Word

我想有时将我的摘要统计信息打印到控制台,有时也打印到 Word。

我不希望我的代码中充斥着调用 Word 的行,因为每次我只需要控制台输出时,我都需要查找并注释掉大约 100 行。

我考虑过在前面使用一个标志变量,当我想打印而不是打印时将其更改为 false,但这也很麻烦。

我想到的最佳解决方案是编写一个单独的脚本来打开一个文档,通过调用我的第一个摘要统计脚本来编写,然后关闭该文档:

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()

但是,当我尝试使用 python docx 执行上述操作时,在打开我的文档文件时收到错误 We're sorry, we can't open this document because some parts are missing or invalid. 如您所见,上面的代码只是打印出一个数字,所以它不能'我正在尝试写入的数据没有问题。

最后,需要转到Word而不是其他文件格式,来格式化一些数据表。

顺便说一下,这是 RunSummaryStats 的摘录。您可以看到它是如何充满打印行的,这在我仍在探索数据时很有用,而且我不想通过添加到列表中来摆脱 of/replace:

Document() constructor essentially creates the .docx file package(这实际上是 XML 的 lots 和其他内容的 .zip 存档,后来 Word应用程序解析和呈现等)。

此语句 f = open(filename, 'w') 打开该文件对象(注意:这不会打开 Word 应用程序,也不会打开 Word 文档实例),然后将标准输出转储到该对象中。那是 100% 的时间会导致损坏的 Word 文档;因为您根本无法 以这种方式将 写入 word 文档。您基本上是在创建一个带有 docx 扩展名的纯文本文件,但是底层 "guts" 的 none 使 docx 成为 docx。结果,Word 应用程序不知道如何处理它。

修改您的代码,使此 "summary" 过程 returns 成为一个可迭代对象(此可迭代对象中的项目将是您要放入 Word 文档中的任何内容)。然后您可以使用类似 add_paragraph 的方法将每个项目添加到 Word 文档。

def get_summary_stats(console=False):
    """
        if console==True, results will be printed to console
        returns a list of string for use elsewhere
    """
    # hardcoded, but presume you will actually *get* these information somehow, modify as needed:
    stats = ["some statistics about something", "more stuff about things"]
    if console:
        for s in stats:
            print(s)
    return stats

然后:

filename = "demo.docx"
document = Document()

# True will cause this function to print to console
for stat in get_summary_stats(True):
    document.add_paragraph(stat)
document.save(filename)

最简单的方法是让 cStringIO 完成工作,并将收集所有数据与将数据写入文件分开。即:

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)

所以也许有更好的方法,但最后我

  1. 从我的摘要统计脚本中创建了一个函数 def run_summary
  2. 根据@Charles Duffy 的回答def print_word 创建了一个函数,其中 StringIORunSummaryStats.run_summary(filepath, filename)
  3. 读取
  4. 在我的最后一个模块中调用了 def_print_word。我在那里设置了路径、文件名和原始数据源的变量,如下所示:

PrintScriptToWord.print_word(ATSpath, RSBSfilename, curr_file + ".docx")

我欢迎任何改进此方法或其他方法的建议。