перенаправить печать в файл журнала - PullRequest
26 голосов
/ 25 марта 2010

Хорошо. Я завершил свою первую программу на Python. В ней около 1000 строк кода. Во время разработки я поместил множество операторов print перед выполнением команды, использующей os.system() скажи что-то вроде

print "running command",cmd
os.system(cmd)

Теперь я закончил программу. Я думал о том, чтобы комментировать их, но перенаправление всех этих ненужных отпечатков (я не могу удалить все операторы print - поскольку некоторые предоставляют полезную информацию для пользователя) в файл журнала будет более полезным? Любые хитрости или советы.

Ответы [ 8 ]

46 голосов
/ 25 марта 2010

Вы должны взглянуть на модуль регистрации Python


РЕДАКТИРОВАТЬ: Образец кода:

import logging

if __name__ == "__main__":
    logging.basicConfig(level=logging.DEBUG, filename="logfile", filemode="a+",
                        format="%(asctime)-15s %(levelname)-8s %(message)s")
    logging.info("hello")

Создать файл с именем «logfile» с содержанием:

2012-10-18 06:40:03,582 INFO     hello
43 голосов
/ 25 марта 2010

Python позволяет вам захватывать и назначать sys.stdout - как уже упоминалось - для этого:

import sys
old_stdout = sys.stdout

log_file = open("message.log","w")

sys.stdout = log_file

print "this will be written to message.log"

sys.stdout = old_stdout

log_file.close()
8 голосов
/ 25 марта 2010
  • В следующий раз вы будете счастливее, если вместо использования операторов print использовать модуль logging с самого начала.Он обеспечивает необходимый элемент управления, и вы можете записать его в стандартный вывод, пока он там, где вы хотите.

  • Многие люди здесь предлагают перенаправить стандартный вывод. Это уродливое решение. Он мутирует глобальный и, что еще хуже, мутирует его для использования этого модуля.Я бы скорее сделал регулярное выражение, которое изменяет все print foo на print >>my_file, foo и задает my_file либо stdout, либо фактический файл по моему выбору.

    • Если у вас есть какие-либо другие части приложениячто на самом деле зависит от записи в стандартный вывод (или когда-либо будет в будущем, но вы еще этого не знаете), это нарушает их.Даже если вы этого не сделаете, чтение вашего модуля будет выглядеть так, как будто оно делает одно, а на самом деле делает другое, если вы пропустили одну маленькую строчку вверху.
    • Печать Chevron довольно уродливая, но не такая страшнаявременно изменяя sys.stdout для процесса.
    • Очень технически говоря, замена регулярного выражения не способна сделать это правильно (например, она может давать ложные срабатывания, если вы находитесь внутри многострочного строкового литерала).Тем не менее, он может работать, просто следите за ним.
  • os.system практически всегда уступает использованию модуля subprocess.Последний не должен вызывать оболочку, не передает сигналы способом, который обычно нежелателен, и может использоваться неблокирующим образом.

2 голосов
/ 01 декабря 2017

Вы можете создать файл журнала и подготовить его к записи. Затем создайте функцию:

def write_log(*args):
    line = ' '.join([str(a) for a in args])
    log_file.write(line+'\n')
    print(line)

и затем замените имя вашей функции print () на write_log ()

2 голосов
/ 25 марта 2010

Простой способ перенаправить stdout и stderr с помощью модуля регистрации здесь: Как мне скопировать sys.stdout в файл журнала на python?

2 голосов
/ 25 марта 2010

Вы можете перенаправить замену sys.stdout на любой объект, который имеет тот же интерфейс, что и sys.stdout, при записи этого объекта вы можете печатать на терминал и в файл. например смотри этот рецепт http://code.activestate.com/recipes/119404-print-hook/

1 голос
/ 25 марта 2010

Если вы введете свой файл-подобный в sys.stdout, вы сможете захватить вывод текста через print.

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

Просто примечание о режиме добавления и записи. Измените filemode на "w", если вы хотите заменить файл журнала. Я также должен был закомментировать поток. Затем с помощью logging.info () выводился в указанный файл.

if __name__ == '__main__':
    LOG_FORMAT = '%(asctime)s:%(levelname)s ==> %(message)s'
    logging.basicConfig(
        level=logging.INFO,
        filename="logfile",
        filemode="w",
        format=LOG_FORMAT
        #stream=sys.stdout
    )
...