печать в файл в Python: перенаправление против аргумента файла печати против записи - PullRequest
6 голосов
/ 03 ноября 2010

У меня есть куча print вызовов, которые мне нужно записать в файл вместо stdout. (Мне вообще не нужно stdout)

Я рассматриваю три подхода. Есть ли какие-либо преимущества (включая производительность) для любого из них?

Полный редирект, который я видел здесь :

import sys

saveout = sys.stdout
fsock = open('out.log', 'w')
sys.stdout = fsock

print(x)
# and many more print calls

# later if I ever need it:
# sys.stdout = saveout
# fsock.close()

Перенаправление в каждой инструкции печати:

fsock = open('out.log', 'w')
print(x, file = fsock)
# and many more print calls

Функция записи:

fsock = open('out.log', 'w')
fsock.write(str(x))
# and many more write calls

Ответы [ 3 ]

6 голосов
/ 04 ноября 2010

Я бы не ожидал каких-либо устойчивых различий в производительности между этими подходами.

Преимущество первого подхода состоит в том, что любой разумно корректный код, на который вы полагаетесь (модули, которые вы импортируете), автоматически выбирает желаемое перенаправление.

Второй подход не имеет преимуществ. Он подходит только для отладки или одноразового кода ... и даже не очень хорошая идея для этого. Вы хотите, чтобы ваши выходные решения были консолидированы в нескольких четко определенных местах, а не разбросаны по всему коду при каждом вызове print(). В Python3 print() является функцией, а не оператором. Это позволяет вам переопределить его, если хотите. Так что вы можете def print(*args), если хотите. Вы также можете позвонить __builtins__.print(), если вам нужен доступ к нему, например, в рамках определения вашего собственного пользовательского print().

Третий подход ... и, следовательно, принцип, согласно которому все ваши выходные данные должны генерироваться в определенных функциях и методах классов, которые вы определяете для этой цели ..., вероятно, лучше всего.

Вы должны максимально отделить вывод и форматирование от основных функций. Храня их отдельно, вы позволяете вашему ядру быть повторно использованным. (Например, вы можете начать с чего-то, что предназначено для запуска из текстовой консоли или консоли, а затем вам потребуется предоставить веб-интерфейс, полноэкранный интерфейс (curses) или графический интерфейс пользователя. Вы также можете создать совершенно другую функциональность вокруг него ... в ситуациях, когда результирующие данные необходимо возвращать в их исходной форме (как объекты), а не извлекать как текст (вывод) и повторно анализировать в новые объекты.

Например, у меня было несколько случаев, когда что-то, что я писал, выполняло сложные запросы и собирал данные из разных источников и печатал отчет ... скажем о расхождениях ... позже необходимо адаптировать его в форму которые могут выдавать данные в некоторой форме (например, YAML / JSON), которые могут быть переданы в другую систему (скажем, для согласования одного источника данных с другим.

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

4 голосов
/ 03 ноября 2010

Я думаю, что семантика важна:

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

Второй и третий подход немного отличаются в случае, если вы печатаете текстовые строки. Второй подход - print добавляет символ новой строки, а write - нет.

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

4 голосов
/ 03 ноября 2010

Из имен файлов, которые вы используете в своем вопросе, похоже, что вы хотите создать файл журнала.Вы рассматривали модуль Python logging вместо?

...