我想使用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)
这是我用来打印到文件/日志的另一种方法…修改内置的打印函数,使其记录到具有当前时间戳的temp目录中的文件,并打印到stdout。在脚本中这样做的唯一真正好处是不需要去修改现有的打印语句。
print('test')
test
复制原始打印函数到新变量
og_print = print
og_print('test2')
test2
覆盖现有的打印功能
def print(*msg):
'''print and log!'''
# import datetime for timestamps
import datetime as dt
# convert input arguments to strings for concatenation
message = []
for m in msg:
message.append(str(m))
message = ' '.join(message)
# append to the log file
with open('/tmp/test.log','a') as log:
log.write(f'{dt.datetime.now()} | {message}\n')
# print the message using the copy of the original print function to stdout
og_print(message)
print('test3')
test3
显示文件
cat /tmp/test.log
2022-01-25 10:19:11.045062 | test3
删除文件
rm /tmp/test.log
最明显的方法是打印到一个文件对象:
with open('out.txt', 'w') as f:
print('Filename:', filename, file=f) # Python 3.x
print >> f, 'Filename:', filename # Python 2.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()
从Python 3.4开始,就有一个简单的上下文管理器可以在标准库中做到这一点:
from contextlib import redirect_stdout
with open('out.txt', 'w') as f:
with redirect_stdout(f):
print('data')
从shell本身向外部重定向是另一种选择,通常是更可取的:
./script.py > out.txt
其他问题:
你的脚本的第一个文件名是什么?我没有看到它被初始化。
我的第一个猜测是glob没有找到任何bamfile,因此for循环不会运行。检查文件夹是否存在,并在脚本中打印bamfiles。
同样,使用os.path.join和os.path.basename来操作路径和文件名。
在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))
你可以用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')))