我想使用Python将打印重定向到一个.txt文件。我有一个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/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)
在python 3中,你可以重新赋值print:
#!/usr/bin/python3
def other_fn():
#This will use the print function that's active when the function is called
print("Printing from function")
file_name = "test.txt"
with open(file_name, "w+") as f_out:
py_print = print #Need to use this to restore builtin print later, and to not induce recursion
print = lambda out_str : py_print(out_str, file=f_out)
#If you'd like, for completeness, you can include args+kwargs
print = lambda *args, **kwargs : py_print(*args, file=f_out, **kwargs)
print("Writing to %s" %(file_name))
other_fn() #Writes to file
#Must restore builtin print, or you'll get 'I/O operation on closed file'
#If you attempt to print after this block
print = py_print
print("Printing to stdout")
other_fn() #Writes to console/stdout
注意,来自other_fn的print仅切换输出,因为print在全局作用域中被重新赋值。如果在函数中赋值print, other_fn中的print通常不受影响。如果我们想影响所有的打印调用,我们可以使用global关键字:
import builtins
def other_fn():
#This will use the print function that's active when the function is called
print("Printing from function")
def main():
global print #Without this, other_fn will use builtins.print
file_name = "test.txt"
with open(file_name, "w+") as f_out:
print = lambda *args, **kwargs : builtins.print(*args, file=f_out, **kwargs)
print("Writing to %s" %(file_name))
other_fn() #Writes to file
#Must restore builtin print, or you'll get 'I/O operation on closed file'
#If you attempt to print after this block
print = builtins.print
print("Printing to stdout")
other_fn() #Writes to console/stdout
就我个人而言,我更倾向于通过将输出文件描述符烘焙到一个新函数中来避免使用print函数的要求:
file_name = "myoutput.txt"
with open(file_name, "w+") as outfile:
fprint = lambda pstring : print(pstring, file=outfile)
print("Writing to stdout")
fprint("Writing to %s" % (file_name))
你可能不喜欢这个答案,但我认为这是正确的答案。除非绝对必要,否则不要改变你的标准输出目标(也许你使用的库只输出到标准输出??这里显然不是这样)。
我认为作为一个好习惯,你应该提前准备好你的数据作为一个字符串,然后打开你的文件,并立即写入整个东西。这是因为输入/输出操作打开文件句柄的时间越长,该文件发生错误的可能性就越大(文件锁定错误、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')
然后,当你收集了你的“数据线”,每个列表项一行,你可以用一些'\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()
你可以用file参数重定向打印(在python2中有>>操作符代替)。
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')))