您的位置:首页 > 编程语言 > Python开发

转:python重定向标准输入、标准输出和标准错误

2013-11-26 21:57 513 查看
UNIX用户已经对标准输入、标准输出和标准错误的概念熟悉了。这一节是为其它不熟悉的人准备的。

标准输出和标准错误(通常缩写为stdout和stderr)是建立在每个UNIX系统内的管道(pipe)。当你print某东西时,结果输出到stdout管道中;当你的程序崩溃并打印出调试信息时(象Python中的错误跟踪),结果输出到stderr管道中。通常这两个管道只与你正在工作的终端窗口相联,所以当一个程序打印输出时,你可以看到输出,并且当一个程序崩溃时,你可以看到调试信息。(如果你在一个基于窗口的PythonIDE系统上工作,stdout和stderr缺省为“交互窗口”。)

例5.32.stdout和stderr介绍

>>>foriinrange(3):
...print'Divein'




Divein
Divein
Divein
>>>importsys
>>>foriinrange(3):
...sys.stdout.write('Divein')




DiveinDiveinDivein
>>>foriinrange(3):
...sys.stderr.write('Divein')




DiveinDiveinDivein




正如我们在例3.28中看到的,我们可以使用Python内置的range函数来创建简单的计数循环,即重复某物一定的次数。



stdout是一个类文件对象;调用它的write函数会打印出任何给出的字符串。事实上,这就是print函数真正所做的;它会在正打印的字符串后面加上回车换行符,并调用sys.stdout.write。



在最简单的例子中,stdout和stderr将它们的输出发送到同一个地方:PythonIDE,或终端(如果你正从命令行运行Python)。象stdout,stderr并不为你增加回车换行符;如果需要,要自已加上。

stdout和stderr都是类文件对象,就象我们在提取输入源中所讨论的一样,但它们都是只写的。它们没有read方法,只有write。然而,它们的确是类文件对象,并且你可以将任意文件对象或类文件对象赋给它们来重定向输出。

例5.33.重定向输出

[f8dy@oliverkgp]$python2stdout.py
Divein
[f8dy@oliverkgp]$catout.log
Thismessagewillbeloggedinsteadofdisplayed

如果你还没有这样做,你可以下载本书中用到的本例和其它例子。

#stdout.py
importsys

print'Divein'




saveout=sys.stdout




fsock=open('out.log','w')




sys.stdout=fsock




print'Thismessagewillbeloggedinsteadofdisplayed'




sys.stdout=saveout




fsock.close()






这样会打印到IDE的“交互窗口”中(或终端,如果你从命令行运行这一脚本)。



始终在重定向stdout之前保存它,这样你可以在后面将其设回正常。



打开一个新文件用于写入。


将所有后续的输出重定向到我们刚打开的新文件上。



这样只会将输出结果“打印”到日志文件中;在IDE窗口中或在屏幕上不会看到输出结果。



在我们将stdout搞乱之前,让我们把它设回原来的方式。



关闭日志文件。
重定向stderr完全以相同的方式进行,用sys.stderr代替sys.stdout。

例5.34.重定向错误信息

[f8dy@oliverkgp]$python2stderr.py
[f8dy@oliverkgp]$caterror.log
Traceback(mostrecentlinelast):
File"stderr.py",line5,in?
raiseException,'thiserrorwillbelogged'
Exception:thiserrorwillbelogged

如果你还没有这样做,你可以下载本书中用到的本例和其它例子。

#stderr.py
importsys

fsock=open('error.log','w')




sys.stderr=fsock




raiseException,'thiserrorwillbelogged'










打开我们想用来存储调试信息的日志文件。



将我们新打开的日志文件的文件对象赋给stderr重定向标准错误。



引发一个异常。从屏幕输出上我们可以注意到这样没有在屏幕上打印出任何东西。所以正常跟踪信息已经写进error.log。



还要注意我们既没有显示地关闭日志文件,也没有将stderr设回它的初始值。这样挺好,因为一旦程序崩溃(由于我们的异常),Python将替我们清理和关闭文件,并且stderr永远不恢复不会造成什么不同。因为,我提到过,一旦程序崩溃,则Python也结束。如果你希望在同一个脚本的后面去做其它的事情,恢复初始值对stdout更为重要。

另一方面,标准输入是只读文件对象,同时它表示从前面某个程序的数据流入这个程序。这一点可能对典型的MacOS用户可能没什么意义,或者甚至是对Windows用户也是如此,除非你更习惯在MS-DOS命令行下工作。它的工作方式是:你可以在单个文件中构造一个命令行的链,这样一个程序的输出成为链中下一个程序的输入。第一个程序简单地输出到标准输出(本身不需要任何特别的重定义,只是执行正常的print什么的),同时下个程序从标准输入读入,操作系统会小心地将一个程序的输出连接到下一个程序的输入。

例5.35.链接命令

[f8dy@oliverkgp]$python2kgp.py-gbinary.xml




01100111
[f8dy@oliverkgp]$catbinary.xml




<?xmlversion="1.0"?>
<!DOCTYPEgrammarPUBLIC"-//diveintopython.org//DTDKantGeneratorProv1.0//EN""kgp.dtd">
<grammar>
<refid="bit">
<p>0</p>
<p>1</p>
</ref>
<refid="byte">
<p><xrefid="bit"/><xrefid="bit"/><xrefid="bit"/><xrefid="bit"/>\
<xrefid="bit"/><xrefid="bit"/><xrefid="bit"/><xrefid="bit"/></p>
</ref>
</grammar>
[f8dy@oliverkgp]$catbinary.xml|python2kgp.py-g-








10110001




正如我们在接触中看到的,这样会打印出8个随机比特(0或1)的字符串。



这样会简单地打印出binary.xml的全部内容。(Windows用户应该使用type代替cat。)



这样会打印binary.xml的内容,但是“|”字符,叫做管道符,表示输出内容不会打印到屏幕上。相反,它们成为下个命令(在本例中调用我们的Python脚本)的标准输入。



我们没有指定一个模块(象binary.xml),而是指定“-”,这会让我们的脚本从标准输入而不是从磁盘上的一个特别文件中装入语法。(在下个例子中有更多关于它是如何发生的内容。)这样效果同第一个语法(我们直接指定语法文件名)是一样的,但它考虑了这里的扩展的可能性。不只是简单地执行catbinary.xml,我们可以运行一个可以动态生成语法的脚本,然后可以将它通过管道输入到我们的脚本中。语法可以来自任何地方:数据库,或某个语法生成元脚本什么的。要点就是我们完全不必修改我们的kgp.py脚本就可以同任何这种功能进行合并。我们要做的只是能够从标准输入中接收语法文件,并且我们可以将所有其它的逻辑分散到另一个程序中。

那么当语法文件是“-”时我们的脚本是如何中从标准输入读入的呢?没什么神秘的,就是编码。

例5.36.在kgp.py中从标准输入读入

defopenAnything(source):
ifsource=="-":




importsys
returnsys.stdin

#trytoopenwithurllib(ifsourceishttp,ftp,orfileURL)
importurllib
try:

[...略...]




这是来自toolbox.py中的openAnything函数,我们在提取输入源中讨论过的。我们所做的全部是在函数的开始处添加三行代码,用来检查是否source是“-”,如果是,我们返回sys.stdin。实际上,就是这样!记住,stdin是一个带有read方法的类文件对象,所以我们代码的其余部分(在kgp.py中,我们调用openAnything的地方)一点没有改变

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: