Как перенаправить вывод "print" в файл с помощью python?

Я хочу перенаправить печать на a .txt-файл с использованием python. У меня есть цикл "for", который будет "печатать" вывод для каждого из моих .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/xug/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!'
    ........print....
    ........print....

Так в чем проблема? Любой другой способ, кроме этой системы.в stdout?

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

Filename: ERR001268.bam
Readlines finished!
Mean: 233
SD: 10
Interval is: (213, 252)

10 ответов


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

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

однако, перенаправление stdout также работает для меня. Это, вероятно, хорошо для одноразового скрипта, такого как это:

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()

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

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

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


вы можете перенаправить печать с >> оператора.

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

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

f.write('whatever')

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

f.write(' '.join(('whatever', str(var2), 'etc')))

Python 2 или Python 3 ссылка на API:

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

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

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

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

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

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

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

Это прекрасно работает:

import sys
sys.stdout=open("test.txt","w")
print ("hello")
sys.stdout.close()

Теперь "Привет" будет написано тест.txt-файл. Обязательно закройте stdout С close, без него содержимое не будет сохранено в файле


самое простое решение не через python; его через оболочку. Из первой строки вашего файла (#!/usr/bin/python) Я предполагаю, что вы находитесь в системе UNIX. Просто используйте print операторы, как вы обычно, и не открывайте файл вообще в своем скрипте. Когда вы идете, чтобы запустить файл, а не

./script.py

запустить файл, используйте

./script.py > <filename>

где вместо <filename> С именем файла, в который вы хотите ввести вывод. The > токен говорит (большинство) оболочки для установки stdout в файл, описанный следующим маркером.

одна важная вещь, которая должна быть упомянута здесь, это то, что "script.py" необходимо сделать исполняемый файл для ./script.py запустить.

поэтому перед запуском ./script.pyвыполнить следующую команду

chmod a+x script.py (сделайте скрипт исполняемым для всех пользователей)


не используйте 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

если вы хотите напечатать в stdout:

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.


вам может не понравиться этот ответ, но я думаю, что это правильный. Не меняйте место назначения stdout, если это не абсолютно необходимо (возможно, вы используете библиотеку, которая выводит только stdout??? здесь явно не так).

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

вот пример:

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

а затем, когда вы все закончите собирать свои "строки данных" по одной строке на элемент списка, вы можете присоединиться к ним с некоторыми '\n' символы, чтобы сделать все это outputtable; может даже обернуть ваше заявление выход в with блок, для дополнительной безопасности (автоматически закроет ваш выход справится даже если что-то пойдет не так):

out_string = '\n'.join(out_lines)
out_filename = 'myfile.txt'
with open(out_filename, 'w') as outf:
    outf.write(out_string)
print "YAY MY STDOUT IS UNTAINTED!!!"

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

out_filename = 'myfile.txt'
outf = open(out_filename, 'w')
for bamfile in bamfiles:
    filename = bamfile.split('/')[-1]
    outf.write('Filename: %s' % filename)
    samtoolsin = subprocess.Popen(["/share/bin/samtools/samtools","view",bamfile],
                                  stdout=subprocess.PIPE,bufsize=1)
    mydata = samtoolsin.stdout.read()
    outf.write(mydata)
outf.close()

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

ваша ошибка где-то еще:

  • это может быть в коде, который вы удалили для своего вопроса (Откуда берется имя файла для вызова, чтобы открыть?)
  • также может быть, что вы не ждете, пока данные будут сброшены: если вы печатаете на терминале, данные сброшены после каждой новой строки, но если вы печатаете в файл, он сбрасывается только тогда, когда буфер stdout заполнен (4096 байт в большинстве систем).

Если ur использует linux, я предлагаю u использовать tee команда реализация идет как этот python python_file.py |tee any_file_name.txt если вы не хотите ничего менять в коде, я думаю ,что это может быть лучшим решением, вы также можете реализовать logger, но вам нужно внести некоторые изменения в код.


что-то, чтобы расширить функцию печати для циклов

x = 0
while x <=5:
    x = x + 1
    with open('outputEis.txt', 'a') as f:
        print(x, file=f)
    f.close()