如何使用python将“打印”输出redirect到一个文件?

我想使用python将打印redirect到.txt文件。 我有一个'for'循环,它将'打印'我的每个.bam文件的输出,而我想将所有这些输出redirect到一个文件。 所以我试图把

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.... 

所以有什么问题? 除了这个sys.stdout以外的其他任何方式?

我需要我的结果如下所示:

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

最明显的方法是打印到一个文件对象:

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

但是,redirect标准输出也适用于我。 对于像这样的一次性脚本来说可能是好的:

 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.path.join和os.path.basename来处理path和文件名。

您可以使用>>操作符redirect打印。

 f = open(filename,'w') print >>f, 'whatever' 

在大多数情况下,你最好是正常写文件。

 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)

file参数必须是带有write(string)方法的对象; 如果它不存在或None ,将使用sys.stdout 。 由于打印的参数被转换为文本string, 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) 

这完美地工作:

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

现在hello将被写入test.txt文件。 确保closuresstdout close ,没有它的内容不会保存在文件中

最简单的解决scheme不是通过python; 它通过壳。 从你的文件的第一行( #!/usr/bin/python )我猜你正在UNIX系统上。 只要像平时一样使用print语句,并且不要在脚本中打开文件。 当你去运行文件,而不是

 ./script.py 

运行该文件,使用

 ./script.py > <filename> 

在那里你用你想要输出的文件的名字replace<filename>>标记告诉(大部分)shell将stdout设置为由以下标记描述的文件。

这里需要提到的一个重要的事情就是需要将“script.py”设置为可执行文件来运行./script.py

所以在运行./script.py之前,执行这个命令

chmod a+x script.py (使脚本对所有用户可执行)

你可能不喜欢这个答案,但我认为这是正确的。 不要改变你的标准输出目的地,除非它是绝对必要的(也许你正在使用只输出到标准输出的库???显然不是这里的情况)。

我认为作为一个好习惯,你应该提前准备好你的数据作为一个string,然后打开你的文件,一次写完所有的东西。 这是因为input/输出操作是打开文件句柄的时间越长,这个文件就越可能发生错误(文件locking错误,I / O错误等)。 只要在一个操作中做到这一点,就不会出现什么时候可能出错的问题。

这是一个例子:

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

然后,当你完成了每个列表项目一行的“数据行”的收集工作时,你可以join一些'\n'字符来使整个事情成为可能。 甚至可能将你的输出语句包含在block中,以提高安全性(即使出现错误,也会自动closures输出句柄):

 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的值确实会更改要打印的所有调用的目标。 如果您使用其他方式更改打印目标,则会得到相同的结果。

你的bug在别的地方:

  • 它可能在您为您的问题删除的代码(文件名来自打开电话的地方?)
  • 也可能是因为不等待数据刷新:如果在terminal上打印,每隔一行新数据就会刷新一次,但是如果打印到一个文件,只有当标准输出缓冲区已满时才会刷新数据(4096字节在大多数系统上)。

有些东西可以扩展循环的打印function

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