如何使用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()