如何使用python将“打印”输出重定向到文件?

时间:2021-02-27 21:45:34

I want to redirect the print to a .txt file using python. I have a 'for' loop, which will 'print' the output for each of my .bam file while I want to redirect ALL these output to one file. So I tried to put

我想使用python将打印重定向到.txt文件。我有一个“for”循环,它将“打印”我的每个.bam文件的输出,同时我想将所有这些输出重定向到一个文件。所以我试着说。

 f = open('output.txt','w'); sys.stdout = f

at the beginning of my script. However I get nothing in the .txt file. My script is:

在我剧本的开头。但是我在。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....

So what's the problem? Any other way besides this sys.stdout?

所以有什么问题?除此之外,还有别的方法吗?

I need my result look like:

我需要我的结果是:

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

10 个解决方案

#1


141  

The most obvious way to do this would be to print to a file object:

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

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

However, redirecting stdout also works for me. It is probably fine for a one-off script such as this:

然而,重定向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()

What is the first filename in your script? I don't see it initialized.

脚本中的第一个文件名是什么?我没有看到初始化。

My first guess is that glob doesn't find any bamfiles, and therefore the for loop doesn't run. Check that the folder exists, and print out bamfiles in your script.

我的第一个猜测是glob没有找到任何bamfiles,因此for循环不会运行。检查文件夹是否存在,并在脚本中打印bamfiles。

Also, use os.path.join and os.path.basename to manipulate paths and filenames.

此外,使用os.path。加入和os.path。basename可以操作路径和文件名。

#2


39  

You can redirect print with the >> operator.

可以使用>>操作符重定向打印。

f = open(filename,'w')
print >>f, 'whatever'     # Python 2.x
print('whatever', file=f) # Python 3.x

In most cases, you're better off just writing to the file normally.

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

f.write('whatever')

or, if you have several items you want to write with spaces between, like print:

或者,如果你有几个项目你想用空格来写,比如打印:

f.write(' '.join(('whatever', str(var2), 'etc')))

#3


26  

Python 2 or Python 3 API reference:

Python 2或Python 3 API参考:

print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False)

打印(*对象,sep=' ', end='\n', file=sys)。stdout,冲洗= False)

The file argument must be an object with a write(string) method; if it is not present or None, sys.stdout will be used. Since printed arguments are converted to text strings, print() cannot be used with binary mode file objects. For these, use file.write(...) instead.

文件参数必须是具有写(字符串)方法的对象;如果它不存在或不存在,请系统。将使用标准输出。由于打印的参数被转换为文本字符串,所以print()不能与二进制模式文件对象一起使用。对于这些,使用file.write(…)代替。

Since file object normally contains write() method, all you need to do is to pass a file object into its argument.

由于file对象通常包含write()方法,所以您只需将文件对象传递到其参数中。

Write/Overwrite to File

with open('file.txt', 'w') as f:
    print('hello world', file=f)

Write/Append to File

with open('file.txt', 'a') as f:
    print('hello world', file=f)

#4


21  

This works perfectly:

这是完美的:

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

Now the hello will be written to the test.txt file. Make sure to close the stdout with a close, without it the content will not be save in the file

现在hello将被写入到测试中。txt文件。确保关闭stdout,否则内容将不会保存到文件中

#5


10  

The easiest solution isn't through python; its through the shell. From the first line of your file (#!/usr/bin/python) I'm guessing you're on a UNIX system. Just use print statements like you normally would, and don't open the file at all in your script. When you go to run the file, instead of

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

./script.py

to run the file, use

要运行文件,请使用

./script.py > <filename>

where you replace <filename> with the name of the file you want the output to go in to. The > token tells (most) shells to set stdout to the file described by the following token.

替换为要输入的文件的名称。>令牌告诉(大多数)shell将stdout设置为以下令牌描述的文件。

One important thing that needs to be mentioned here is that "script.py" needs to be made executable for ./script.py to run.

这里需要提到的一件重要的事情是“脚本”。py"需要为。/脚本执行。py运行。

So before running ./script.py,execute this command

所以之前运行。/脚本。py,执行这个命令

chmod a+x script.py (make the script executable for all users)

chmod + x脚本。py(使脚本可为所有用户执行)

#6


5  

Don't use print, use logging

You can change sys.stdout to point to a file, but this is a pretty clunky and inflexible way to handle this problem. Instead of using print, use the logging module.

您可以更改系统。指向一个文件,但是这是一个非常笨拙和不灵活的方法来处理这个问题。使用日志模块,而不是使用print。

With logging, you can print just like you would to stdout, or you can also write the output to a file. You can even use the different message levels (critical, error, warning, info, debug) to, for example, only print major issues to the console, but still log minor code actions to a file.

使用日志记录,可以像输出stdout那样打印,也可以将输出写到文件中。您甚至可以使用不同的消息级别(关键的、错误的、警告的、信息的、调试的),例如,只将主要问题打印到控制台,但是仍然将小的代码操作记录到文件中。

A simple example

Import logging, get the logger, and set the processing level:

导入日志记录,获取日志记录器,并设置处理级别:

import logging
logger = logging.getLogger()
logger.setLevel(logging.DEBUG) # process everything, even if everything isn't printed

If you want to print to stdout:

如果你想打印到stdout:

ch = logging.StreamHandler()
ch.setLevel(logging.INFO) # or any other level
logger.addHandler(ch)

If you want to also write to a file (if you only want to write to a file skip the last section):

如果你也想写一个文件(如果你只想写一个文件,请跳过最后一节):

fh = logging.FileHandler('myLog.log')
fh.setLevel(logging.DEBUG) # or any level you want
logger.addHandler(fh)

Then, wherever you would use print use one of the logger methods:

然后,无论您在哪里使用打印,请使用日志记录器方法之一:

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

To learn more about using more advanced logging features, read the excellent logging tutorial in the Python docs.

要了解更多关于使用更高级的日志功能的信息,请阅读Python文档中的优秀日志教程。

#7


4  

You may not like this answer, but I think it's the RIGHT one. Don't change your stdout destination unless it's absolutely necessary (maybe you're using a library that only outputs to stdout??? clearly not the case here).

你可能不喜欢这个答案,但我认为它是正确的。除非必要,否则不要更改stdout目的地(也许您使用的库只输出stdout???)显然这里不是这样)。

I think as a good habit you should prepare your data ahead of time as a string, then open your file and write the whole thing at once. This is because input/output operations are the longer you have a file handle open, the more likely an error is to occur with this file (file lock error, i/o error, etc). Just doing it all in one operation leaves no question for when it might have gone wrong.

我认为,作为一个好习惯,您应该提前将数据准备为字符串,然后打开您的文件并立即编写整个文件。这是因为打开文件句柄的时间越长,该文件出现错误的可能性就越大(文件锁定错误、i/o错误等等)。仅仅在一次操作中完成所有操作就毫无疑问会在什么时候出错。

Here's an example:

这里有一个例子:

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

And then when you're all done collecting your "data lines" one line per list item, you can join them with some '\n' characters to make the whole thing outputtable; maybe even wrap your output statement in a with block, for additional safety (will automatically close your output handle even if something goes wrong):

然后当你完成收集你的“数据线”每一个列表项的一行时,你可以加入一些“\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!!!"

However if you have lots of data to write, you could write it one piece at a time. I don't think it's relevant to your application but here's the alternative:

但是如果你有很多数据要写,你可以一次写一块。我不认为这与你的申请相关,但这里有另一种选择:

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

#8


0  

Changing the value of sys.stdout does change the destination of all calls to print. If you use an alternative way to change the destination of print, you will get the same result.

改变sys的值。stdout会更改要打印的所有调用的目的地。如果您使用另一种方法来更改打印的目的地,您将得到相同的结果。

Your bug is somewhere else:

你的错误在别的地方:

  • it could be in the code you removed for your question (where does filename come from for the call to open?)
  • 它可能在您为您的问题而删除的代码中(文件名从哪里来,以便调用打开?)
  • it could also be that you are not waiting for data to be flushed: if you print on a terminal, data is flushed after every new line, but if you print to a file, it's only flushed when the stdout buffer is full (4096 bytes on most systems).
  • 也可能是您没有等待数据被刷新:如果您在一个终端上打印,数据会在每个新行之后被刷新,但是如果您将数据打印到一个文件中,那么只有当stdout缓冲区满时才会被刷新(大多数系统的4096字节)。

#9


0  

if ur using linux i suggest u to use tee command the implementation goes like this python python_file.py |tee any_file_name.txt if u dont want to change anything in the code ,i think this might be the best possible solution ,u can also implement logger but u need do some changes in the code.

如果您使用linux,我建议您使用tee命令,实现如下python python_file所示。py |三通any_file_name。如果您不想在代码中更改任何内容,我认为这可能是最好的解决方案,您也可以实现logger,但是您需要在代码中做一些更改。

#10


-1  

Something to extend print function for loops

为循环扩展打印功能

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

#1


141  

The most obvious way to do this would be to print to a file object:

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

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

However, redirecting stdout also works for me. It is probably fine for a one-off script such as this:

然而,重定向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()

What is the first filename in your script? I don't see it initialized.

脚本中的第一个文件名是什么?我没有看到初始化。

My first guess is that glob doesn't find any bamfiles, and therefore the for loop doesn't run. Check that the folder exists, and print out bamfiles in your script.

我的第一个猜测是glob没有找到任何bamfiles,因此for循环不会运行。检查文件夹是否存在,并在脚本中打印bamfiles。

Also, use os.path.join and os.path.basename to manipulate paths and filenames.

此外,使用os.path。加入和os.path。basename可以操作路径和文件名。

#2


39  

You can redirect print with the >> operator.

可以使用>>操作符重定向打印。

f = open(filename,'w')
print >>f, 'whatever'     # Python 2.x
print('whatever', file=f) # Python 3.x

In most cases, you're better off just writing to the file normally.

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

f.write('whatever')

or, if you have several items you want to write with spaces between, like print:

或者,如果你有几个项目你想用空格来写,比如打印:

f.write(' '.join(('whatever', str(var2), 'etc')))

#3


26  

Python 2 or Python 3 API reference:

Python 2或Python 3 API参考:

print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False)

打印(*对象,sep=' ', end='\n', file=sys)。stdout,冲洗= False)

The file argument must be an object with a write(string) method; if it is not present or None, sys.stdout will be used. Since printed arguments are converted to text strings, print() cannot be used with binary mode file objects. For these, use file.write(...) instead.

文件参数必须是具有写(字符串)方法的对象;如果它不存在或不存在,请系统。将使用标准输出。由于打印的参数被转换为文本字符串,所以print()不能与二进制模式文件对象一起使用。对于这些,使用file.write(…)代替。

Since file object normally contains write() method, all you need to do is to pass a file object into its argument.

由于file对象通常包含write()方法,所以您只需将文件对象传递到其参数中。

Write/Overwrite to File

with open('file.txt', 'w') as f:
    print('hello world', file=f)

Write/Append to File

with open('file.txt', 'a') as f:
    print('hello world', file=f)

#4


21  

This works perfectly:

这是完美的:

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

Now the hello will be written to the test.txt file. Make sure to close the stdout with a close, without it the content will not be save in the file

现在hello将被写入到测试中。txt文件。确保关闭stdout,否则内容将不会保存到文件中

#5


10  

The easiest solution isn't through python; its through the shell. From the first line of your file (#!/usr/bin/python) I'm guessing you're on a UNIX system. Just use print statements like you normally would, and don't open the file at all in your script. When you go to run the file, instead of

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

./script.py

to run the file, use

要运行文件,请使用

./script.py > <filename>

where you replace <filename> with the name of the file you want the output to go in to. The > token tells (most) shells to set stdout to the file described by the following token.

替换为要输入的文件的名称。>令牌告诉(大多数)shell将stdout设置为以下令牌描述的文件。

One important thing that needs to be mentioned here is that "script.py" needs to be made executable for ./script.py to run.

这里需要提到的一件重要的事情是“脚本”。py"需要为。/脚本执行。py运行。

So before running ./script.py,execute this command

所以之前运行。/脚本。py,执行这个命令

chmod a+x script.py (make the script executable for all users)

chmod + x脚本。py(使脚本可为所有用户执行)

#6


5  

Don't use print, use logging

You can change sys.stdout to point to a file, but this is a pretty clunky and inflexible way to handle this problem. Instead of using print, use the logging module.

您可以更改系统。指向一个文件,但是这是一个非常笨拙和不灵活的方法来处理这个问题。使用日志模块,而不是使用print。

With logging, you can print just like you would to stdout, or you can also write the output to a file. You can even use the different message levels (critical, error, warning, info, debug) to, for example, only print major issues to the console, but still log minor code actions to a file.

使用日志记录,可以像输出stdout那样打印,也可以将输出写到文件中。您甚至可以使用不同的消息级别(关键的、错误的、警告的、信息的、调试的),例如,只将主要问题打印到控制台,但是仍然将小的代码操作记录到文件中。

A simple example

Import logging, get the logger, and set the processing level:

导入日志记录,获取日志记录器,并设置处理级别:

import logging
logger = logging.getLogger()
logger.setLevel(logging.DEBUG) # process everything, even if everything isn't printed

If you want to print to stdout:

如果你想打印到stdout:

ch = logging.StreamHandler()
ch.setLevel(logging.INFO) # or any other level
logger.addHandler(ch)

If you want to also write to a file (if you only want to write to a file skip the last section):

如果你也想写一个文件(如果你只想写一个文件,请跳过最后一节):

fh = logging.FileHandler('myLog.log')
fh.setLevel(logging.DEBUG) # or any level you want
logger.addHandler(fh)

Then, wherever you would use print use one of the logger methods:

然后,无论您在哪里使用打印,请使用日志记录器方法之一:

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

To learn more about using more advanced logging features, read the excellent logging tutorial in the Python docs.

要了解更多关于使用更高级的日志功能的信息,请阅读Python文档中的优秀日志教程。

#7


4  

You may not like this answer, but I think it's the RIGHT one. Don't change your stdout destination unless it's absolutely necessary (maybe you're using a library that only outputs to stdout??? clearly not the case here).

你可能不喜欢这个答案,但我认为它是正确的。除非必要,否则不要更改stdout目的地(也许您使用的库只输出stdout???)显然这里不是这样)。

I think as a good habit you should prepare your data ahead of time as a string, then open your file and write the whole thing at once. This is because input/output operations are the longer you have a file handle open, the more likely an error is to occur with this file (file lock error, i/o error, etc). Just doing it all in one operation leaves no question for when it might have gone wrong.

我认为,作为一个好习惯,您应该提前将数据准备为字符串,然后打开您的文件并立即编写整个文件。这是因为打开文件句柄的时间越长,该文件出现错误的可能性就越大(文件锁定错误、i/o错误等等)。仅仅在一次操作中完成所有操作就毫无疑问会在什么时候出错。

Here's an example:

这里有一个例子:

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

And then when you're all done collecting your "data lines" one line per list item, you can join them with some '\n' characters to make the whole thing outputtable; maybe even wrap your output statement in a with block, for additional safety (will automatically close your output handle even if something goes wrong):

然后当你完成收集你的“数据线”每一个列表项的一行时,你可以加入一些“\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!!!"

However if you have lots of data to write, you could write it one piece at a time. I don't think it's relevant to your application but here's the alternative:

但是如果你有很多数据要写,你可以一次写一块。我不认为这与你的申请相关,但这里有另一种选择:

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

#8


0  

Changing the value of sys.stdout does change the destination of all calls to print. If you use an alternative way to change the destination of print, you will get the same result.

改变sys的值。stdout会更改要打印的所有调用的目的地。如果您使用另一种方法来更改打印的目的地,您将得到相同的结果。

Your bug is somewhere else:

你的错误在别的地方:

  • it could be in the code you removed for your question (where does filename come from for the call to open?)
  • 它可能在您为您的问题而删除的代码中(文件名从哪里来,以便调用打开?)
  • it could also be that you are not waiting for data to be flushed: if you print on a terminal, data is flushed after every new line, but if you print to a file, it's only flushed when the stdout buffer is full (4096 bytes on most systems).
  • 也可能是您没有等待数据被刷新:如果您在一个终端上打印,数据会在每个新行之后被刷新,但是如果您将数据打印到一个文件中,那么只有当stdout缓冲区满时才会被刷新(大多数系统的4096字节)。

#9


0  

if ur using linux i suggest u to use tee command the implementation goes like this python python_file.py |tee any_file_name.txt if u dont want to change anything in the code ,i think this might be the best possible solution ,u can also implement logger but u need do some changes in the code.

如果您使用linux,我建议您使用tee命令,实现如下python python_file所示。py |三通any_file_name。如果您不想在代码中更改任何内容,我认为这可能是最好的解决方案,您也可以实现logger,但是您需要在代码中做一些更改。

#10


-1  

Something to extend print function for loops

为循环扩展打印功能

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