Как распечатать консоль в текстовый файл ПОСЛЕ завершения программы (Python)?

У меня есть программа, которая выводит множество вычислений и результатов на консоль через оператор печати. Я хочу написать код для экспорта (или сохранения) всего содержимого консоли в простой текстовый файл.

Я искал StackOverflow и другие сайты, но нашел некоторые методы для перенаправления оператора печати для печати в файл напрямую, но я хочу, чтобы программа работала нормально, отображая выходы на консоль, а затем сохраняя ее содержимое ПОСЛЕ всех операций выполненной программы.

Я использую PyCharm с Python2.7, если это важно

Ответ 1

Со всей благодарностью и уважением ко всем, кто внес свой вклад в этот вопрос. Я, наконец, нашел решение этой проблемы с минимальными изменениями в моем исходном коде. Решение предоставляется членом @Status, и вот его ссылка.

Хотя я много искал, прежде чем публиковать свой вопрос, но ответы уважаемых членов озарили мой взгляд на точный поиск, особенно вклад @turkus, который выполняет исключительную работу, и @Glostas, который открыл глаза на "тройник", который посоветовал мне найти решение, которое я разместил (хотя он не содержит "тройник").

Решение, как упоминалось выше, с небольшими изменениями:

1- Поместите в программу следующий класс:

class Logger(object):
"""
Lumberjack class - duplicates sys.stdout to a log file and it okay
source: /questions/49207/how-do-i-duplicate-sysstdout-to-a-log-file-in-python/348798#348798
"""
def __init__(self, filename="Red.Wood", mode="a", buff=0):
    self.stdout = sys.stdout
    self.file = open(filename, mode, buff)
    sys.stdout = self

def __del__(self):
    self.close()

def __enter__(self):
    pass

def __exit__(self, *args):
    pass

def write(self, message):
    self.stdout.write(message)
    self.file.write(message)

def flush(self):
    self.stdout.flush()
    self.file.flush()
    os.fsync(self.file.fileno())

def close(self):
    if self.stdout != None:
        sys.stdout = self.stdout
        self.stdout = None

    if self.file != None:
        self.file.close()
        self.file = None

2- В начале программы перед любыми заявлениями печати поместите эту строку:

my_console = Logger('my_console_file.txt')  # you can change the file name

3- В конце программы, после всех операторов печати, введите следующую строку:

my_console.close()

Я тестировал это, и он отлично работает, и, наконец, у меня есть клон выхода консоли после завершения программы.

С наилучшими пожеланиями всем, и большое спасибо всем участникам.

Ответ 2

Хорошо, поэтому, чтобы это сделать, вам нужно переписать встроенную функцию python print. Но... Есть ipython, который предоставляет некоторые крючки.

Сначала вам нужно установить ipython:

#bash
sudo pip install ipython

(Я использую sudo для простого поиска, затем папку, которую мне нужно достичь, читайте далее)

После установки ipython у вас будет доступная папка расширения ipython, поэтому перейдите к ней:

#bash
cd ~/.ipython/extensions/

и создайте там пусть скажем файл с именем print_to_file.py, вот его содержимое:

#python
class PrintWatcher(object):
    def __init__(self, ip):
        self.shell = ip

    def post_execute(self):
        with open('/home/turkus/shell.txt', 'a+') as f:
            in_len = len(self.shell.user_ns['In'])
            i = in_len - 1

            in_ = self.shell.user_ns['In'][i]
            out = self.shell.user_ns['Out'].get(i, '')
            # you can edit this line if you want different input in shell.txt
            f.write('{}\n{}\n'.format(in_, out))


def load_ipython_extension(ip):
    pw = PrintWatcher(ip)
    ip.events.register('post_run_cell', pw.post_execute)

После сохранения только запускаемого файла:

#bash
ipython profile create 

# you will get something like that:
[ProfileCreate] Generating default config file: u'/home/turkus/.ipython/profile_default/ipython_config.py'

Теперь вернемся к настройке нашего крючка. Мы должны открыть ipython_config.py, созданный по пути выше, и поместить туда какую-нибудь магию (там много чего, так что идите в конец файла):

# some commented lines here
c = get_config()
c.InteractiveShellApp.extensions = [
    'print_to_file'
]

После сохранения его можно запустить ipython и написать свой код. Каждый ваш вход будет записан в файл по пути, указанному выше, в моем случае это было:

/home/turkus/shell.txt

Примечания

Вы можете избежать загрузки расширения каждый раз, когда запускается ipython, просто удалите 'print_to_file' из c.InteractiveShellApp.extensions в списке ipython_config.py. Но помните, что вы можете загрузить его в любое удобное для вас время, просто набрав консоль ipython:

➜  ~ ipython
Python 2.7.12 (default, Jul  1 2016, 15:12:24) 
Type "copyright", "credits" or "license" for more information.

IPython 4.0.0 -- An enhanced Interactive Python.
?         -> Introduction and overview of IPython features.
%quickref -> Quick reference.
help      -> Python own help system.
object?   -> Details about 'object', use 'object??' for extra details.

In [1]: %load_ext print_to_file

Любое изменение в print_to_file.py отражается в открытой оболочке ipython после использования команды %reload_ext print_to_file, поэтому вам не нужно выходить из нее и запускать ее снова.

Ответ 3

Я не уверен, как вы могли получать содержимое консоли для любого редактора, но этого можно добиться достаточно просто, заменив операторы print() на .write

class Writer(object):
    def __init__(self, out_file, overwrite=False):
        self.file_name = out_file
        self.overwrite = overwrite
        self.history = []

    def write(self, statement):
        self.history.append(statement)
        print statement

    def close(self):
        if self.overwrite:
            self.out_file = open(self.file_name, 'wb')
        else:
            self.out_file = open(self.file_name, 'ab')
        for x in self.history:
            self.out_file.write(x+'/n')
        self.out_file.close()
        self.history = []

p = Writer('my_output_file.txt')
p.write('my string to print and save!') 
p.close() #close the writer to save the contents to a file before exiting

Ответ 4

После того, как я понял, понял ваш вопрос, я думаю, что вы ищете команду tee

python your_program | tee output.txt

Это покажет вам выход как в консоли, так и в файле output.txt

PS: Поскольку вы не ответили на мой комментарий, какую ОС используете, я предположил, что вы используете Linux или MACOS. Должен работать на обоих. Я не знаю, как это сделать на окнах...

Ответ 5

Вы можете переопределить функцию print, которая по-прежнему будет доступна через модуль builtins

import builtins

f = open("logs.txt", "w")

def print(*args, sep=' ', end='\n', **kwargs):
    builtins.print(*args, sep=sep, end=end, **kwargs)
    f.write(sep.join(*args) + end)

EDIT: аналогичное решение для Python 2

from __future__ import print_function

class Print:

    def __init__(self, print_function, filename='test', mode='w'):
        self.print_function = print_function
        self.file = open(filename, 'w')

    def __call__(self, *args, **kwargs):
        self.print_function(*args, **kwargs)
        kwargs['file'] = self.file
        self.print_function(*args, **kwargs)

print = Print(print, 'logs.txt')

Это создает функцию print, которую вы используете точно так же, как функция, которую вы импортируете из __future__.
Чтобы закрыть файл, когда все будет сделано, вам нужно запустить:

print.file.close()

Ответ 6

Возможно, вам следует создать переменную, которая будет регистрировать выходы, а затем помещать их в файл.

Для ex:

print statement
logger += statement+"\n" #a new line char so each statement is on a new line

with open('file.txt', 'a') as f:
   f.write(statement)

Ответ 7

Существует очень очевидное, но не очень элегантное решение.

вместо:

print statement 1
calculation
print statement 2

вы можете сделать что-то вроде

sexport =''
calculation
print statement 1
sexport += statement1 + "\n"
calculaztion
print statement 2
sexport += statement 2 

наконец-то просто спасите sexport в файл