Как перенаправить вывод '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')или, если у вас есть несколько элементов, которые вы хотите написать с пробелами между ними, как
f.write(' '.join(('whatever', str(var2), 'etc')))
Python 2 или Python 3 ссылка на API:
print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False)The file аргумент должен быть объектом с
write(string)метод; если его нет илиNone,sys.stdoutбудет использоваться. Поскольку печатные аргументы преобразуются в текстовые строкиprint()не может использоваться с объектами файлов двоичного режима. Для этого используйтеfile.write(...)вместо.С file object как правило, содержит
write()метод, все, что вам нужно сделать, это передать file object в свой аргумент.запись/перезапись в файл
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. Просто используйте./script.pyзапустить файл, используйте
./script.py > <filename>где вместо
<filename>С именем файла, в который вы хотите ввести вывод. Элемент>токен говорит (большинство) оболочки для установки stdout в файл, описанный следующим маркером.одна важная вещь, которая должна быть упомянута здесь, это то, что "script.py" необходимо сделать исполняемый файл для
./script.pyзапустить.так что перед запуском
./script.pyвыполнить следующую команду
chmod a+x script.py(сделайте скрипт исполняемым для всех пользователей)
не используйте
loggingвы можете изменить
sys.stdoutчтобы указать на файл, но это довольно неуклюжий и негибкий способ справиться с этой проблемой. Вместо того, чтобы использовать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)тогда, где бы вы ни использовали
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'символы, чтобы сделать все это выводимым; возможно, даже оберните свой выходной оператор в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 байт в большинстве систем).
Если УР использует linux, я предлагаю вам использовать
teeкоманда реализация идет так pythonpython_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()
Comments