Как перенаправить вывод "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()