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

0
Christina Zhou 8 Июл 2019 в 22:15

3 ответа

Лучший ответ

Самое простое - позволить 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
Charles Duffy 8 Июл 2019 в 19:41

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

  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
Christina Zhou 8 Июл 2019 в 21:03

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

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

Измените ваш код так, чтобы эта «суммарная» процедура возвращала итерацию (элементы в этой итерации будут теми, которые вы хотите поместить в документ Word). Затем вы можете использовать что-то вроде { {X0}} метод добавления каждого элемента в документ 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)
0
David Zemens 8 Июл 2019 в 19:39