Вопрос-Ответ

How to redirect 'print' output to a file?

Как перенаправить вывод 'print' в файл?

Я хочу перенаправить вывод в файл .txt с помощью Python. У меня есть for цикл, который будет print выводить данные для каждого моего файла .bam, в то время как я хочу перенаправить все выходные данные в один файл. Итак, я попытался поместить:

f = open('output.txt','w')
sys.stdout = f

в начале моего скрипта. Однако я ничего не получаю в файле .txt.
Мой скрипт:

#!/usr/bin/python

import os,sys
import subprocess
import glob
from os import path

f = open('output.txt','w')
sys.stdout = f

path= '/home/xxx/nearline/bamfiles'
bamfiles = glob.glob(path + '/*.bam')

for bamfile in bamfiles:
filename = bamfile.split('/')[-1]
print 'Filename:', filename
samtoolsin = subprocess.Popen(["/share/bin/samtools/samtools","view",bamfile],
stdout=subprocess.PIPE,bufsize=1)
linelist= samtoolsin.stdout.readlines()
print 'Readlines finished!'

Так в чем проблема? Есть другой способ, кроме этого sys.stdout?

Мне нужно, чтобы мой результат выглядел как:

Filename: ERR001268.bam
Readlines finished!
Mean: 233
SD: 10
Interval is: (213, 252)
Переведено автоматически
Ответ 1

Наиболее очевидным способом сделать это было бы выполнить печать в файловый объект:

with open('out.txt', 'w') as f:
print('Filename:', filename, file=f) # Python 3.x
# print >> f, 'Filename:', filename # Python 2.x

Однако перенаправление стандартного вывода также работает для меня. Вероятно, это нормально для одноразового скрипта, такого как этот:

import sys

orig_stdout = sys.stdout
f = open('out.txt', 'w')
sys.stdout = f

for i in range(2):
print('i = ', i)

sys.stdout = orig_stdout
f.close()

Начиная с Python 3.4, для этого доступен простой контекстный менеджер в стандартной библиотеке:

from contextlib import redirect_stdout

with open('out.txt', 'w') as f:
with redirect_stdout(f):
print('data')

Перенаправление извне из самой оболочки - еще один вариант, и часто предпочтительнее:

./script.py > out.txt

Другие вопросы:

Какое первое имя файла в вашем скрипте? Я не вижу, чтобы оно было инициализировано.

Мое первое предположение заключается в том, что glob не находит никаких bamfiles, и поэтому цикл for не запускается. Проверьте, существует ли папка, и распечатайте bamfiles в вашем скрипте.

Кроме того, используйте os.path.join и os.path.basename для манипулирования путями и именами файлов.

Ответ 2

Вы можете перенаправить вывод print с помощью file аргумента (в Python 2 вместо него был >> оператор).

f = open(filename,'w')
print('whatever', file=f) # Python 3.x
print >>f, 'whatever' # Python 2.x

В большинстве случаев вам лучше просто записать данные в файл обычным способом.

f.write('whatever')

или, если у вас есть несколько элементов, которые вы хотите записать с пробелами между ними, например print:

f.write(' '.join(('whatever', str(var2), 'etc')))
Ответ 3

Ссылка на APIPython 2 или Python 3:


print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False)


Аргумент file должен быть объектом с write(string) методом; если он отсутствует или None, sys.stdout будет использоваться. Поскольку напечатанные аргументы преобразуются в текстовые строки, print() их нельзя использовать с файловыми объектами в двоичном режиме. Вместо этого используйте file.write(...).


Поскольку файловый объект обычно содержит write() метод, все, что вам нужно сделать, это передать файловый объект в его аргумент.

Запись / Перезапись в файл

with open('file.txt', 'w') as f:
print('hello world', file=f)

Запись / добавление в файл

with open('file.txt', 'a') as f:
print('hello world', file=f)
Ответ 4

Не используйте print, используйте logging

Вы можете изменить sys.stdout, чтобы указать на файл, но это довольно неуклюжий и негибкий способ решения этой проблемы. Вместо использования printиспользуйте logging модуль .

С помощью logging вы можете печатать так же, как и в stdout, или вы также можете записать выходные данные в файл. Вы даже можете использовать другое сообщение уровней (critical, error, warning, info, debug), чтобы, например, печатать только основные вопросы, на консоль, но все равно войти незначительные код действия в файл.

Простой пример

Импортируйте logging, получите logger и установите уровень обработки:

import logging
logger = logging.getLogger()
logger.setLevel(logging.DEBUG) # process everything, even if everything isn't printed

Если вы хотите выполнить печать в стандартный вывод:

ch = logging.StreamHandler()
ch.setLevel(logging.INFO) # or any other level
logger.addHandler(ch)

Если вы хотите также выполнять запись в файл (если вы хотите выполнять запись только в файл, пропустите последний раздел):

fh = logging.FileHandler('myLog.log')
fh.setLevel(logging.DEBUG) # or any level you want
logger.addHandler(fh)

Затем, где бы вы ни использовали, print используйте один из logger методов:

# print(foo)
logger.debug(foo)

# print('finishing processing')
logger.info('finishing processing')

# print('Something may be wrong')
logger.warning('Something may be wrong')

# print('Something is going really bad')
logger.error('Something is going really bad')

Чтобы узнать больше об использовании более продвинутых logging функций, прочтите отличный logging учебник в Python docs.

python