Как инкапсулировать метод для печати консоли в Word - PullRequest
0 голосов
/ 08 июля 2019

Я хочу печатать мою сводную статистику иногда в консоли, а иногда и в 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. Вы можете видеть, как он уже заполнен печатными строками, которые полезны, когда я все еще исследую данные, и от которых я не хочу избавляться / заменять добавлением в список: enter image description here

Ответы [ 3 ]

0 голосов
/ 08 июля 2019

Легко сделать так, чтобы 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)
0 голосов
/ 09 июля 2019

Так что, возможно, был лучший способ сделать это, но в конце концов я

  1. создал одну функцию из моего скрипта сводной статистики def run_summary
  2. создал функцию на основе ответа @Charles Duffy def print_word, где StringIO читает из RunSummaryStats.run_summary(filepath, filename)
  3. называется def_print_word в моем последнем модуле. Там я установил переменные для пути, имени файла и источника необработанных данных следующим образом:

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

Я приветствую любые предложения по улучшению этого или других подходов.

0 голосов
/ 08 июля 2019

Конструктор Document() по сути создает пакет файлов .docx (на самом деле это архив .zip лотов XML и других материалов, которые позже анализируются приложением Word и оказывает и т.д.).

Этот оператор f = open(filename, 'w') открывает этот файловый объект (примечание: он не открывает приложение Word и не открывает экземпляр документа Word), а затем вы выгружаете свой стандартный вывод в этот объект. Это 100% времени приведет к повреждению документа Word; потому что вы просто не можете написать в документ Word таким способом. По сути, вы создаете простой текстовый файл с расширением docx, но ни один из базовых «внутренностей», которые делают docx docx. В результате приложение Word не знает, что с ним делать.

Измените ваш код так, чтобы эта "суммарная" процедура возвращала итерацию (элементы в этой итерации будут теми, которые вы хотите поместить в документ 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)
...