您在这里:主页 > 深入 Python > 脚本和流 > 标准输入、输出和错误 | << >> | ||||
深入 Python从 Python 新手到专家 |
UNIX 用户已经熟悉标准输入、标准输出和标准错误的概念。本节面向其他用户。
标准输出和标准错误(通常缩写为 stdout 和 stderr)是每个 UNIX 系统内置的管道。当您 print 打印内容时,它会进入 stdout 管道;当您的程序崩溃并打印调试信息(如 Python 中的回溯)时,它会进入 stderr 管道。这两个管道通常都连接到您正在使用的终端窗口,因此当程序打印时,您会看到输出,而当程序崩溃时,您会看到调试信息。(如果您使用的是基于窗口的 Python IDE,则 stdout 和 stderr 默认为您的“交互式窗口”。)
>>> for i in range(3): ... print 'Dive in'Dive in Dive in Dive in >>> import sys >>> for i in range(3): ... sys.stdout.write('Dive in')
Dive inDive inDive in >>> for i in range(3): ... sys.stderr.write('Dive in')
Dive inDive inDive in
![]() |
正如您在示例 6.9,“简单计数器” 中看到的,您可以使用 Python 的内置 range 函数来构建简单的计数器循环,以重复执行某个操作一定次数。 |
![]() |
stdout 是一个类似文件的对象;调用其 write 函数将打印您提供的任何字符串。实际上,这就是 print 函数的真正作用;它会在您要打印的字符串末尾添加一个回车符,并调用 sys.stdout.write。 |
![]() |
在最简单的情况下,stdout 和 stderr 将其输出发送到同一个位置:Python IDE(如果您在其中)或终端(如果您从命令行运行 Python)。与 stdout 一样,stderr 不会为您添加回车符;如果您需要,请自行添加。 |
stdout 和 stderr 都是类似文件的对象,就像您在第 10.1 节“抽象输入源” 中讨论的那样,但它们都是只写的。它们没有 read 方法,只有 write 方法。尽管如此,它们仍然是类似文件的对象,您可以将任何其他文件或类似文件的对象分配给它们以重定向其输出。
[you@localhost kgp]$ python stdout.py Dive in [you@localhost kgp]$ cat out.log This message will be logged instead of displayed
(在 Windows 上,您可以使用 type 而不是 cat 来显示文件的内容。)
如果您尚未下载,则可以下载本书中使用的此示例和其他示例。
#stdout.py import sys print 'Dive in'saveout = sys.stdout
fsock = open('out.log', 'w')
sys.stdout = fsock
print 'This message will be logged instead of displayed'
sys.stdout = saveout
fsock.close()
![]()
重定向 stderr 的方法完全相同,使用 sys.stderr 而不是 sys.stdout。
[you@localhost kgp]$ python stderr.py [you@localhost kgp]$ cat error.log Traceback (most recent line last): File "stderr.py", line 5, in ? raise Exception, 'this error will be logged' Exception: this error will be logged
如果您尚未下载,则可以下载本书中使用的此示例和其他示例。
#stderr.py import sys fsock = open('error.log', 'w')sys.stderr = fsock
raise Exception, 'this error will be logged'
![]()
![]()
由于将错误消息写入标准错误非常常见,因此可以使用一种简写语法,而不必完全重定向它。
>>> print 'entering function' entering function >>> import sys >>> print >> sys.stderr, 'entering function'entering function
另一方面,标准输入是一个只读文件对象,它表示从某个先前程序流入程序的数据。对于经典的 Mac OS 用户,甚至 Windows 用户来说,这可能没有多大意义,除非您曾经精通 MS-DOS 命令行。它的工作方式是,您可以在一行中构建一个命令链,以便一个程序的输出成为链中下一个程序的输入。第一个程序只是输出到标准输出(自身不进行任何特殊重定向,只是执行正常的 print 语句或其他操作),下一个程序从标准输入读取,操作系统负责将一个程序的输出连接到下一个程序的输入。
[you@localhost kgp]$ python kgp.py -g binary.xml01100111 [you@localhost kgp]$ cat binary.xml
<?xml version="1.0"?> <!DOCTYPE grammar PUBLIC "-//diveintopythonbook.pythonlang.cn//DTD Kant Generator Pro v1.0//EN" "kgp.dtd"> <grammar> <ref id="bit"> <p>0</p> <p>1</p> </ref> <ref id="byte"> <p><xref id="bit"/><xref id="bit"/><xref id="bit"/><xref id="bit"/>\ <xref id="bit"/><xref id="bit"/><xref id="bit"/><xref id="bit"/></p> </ref> </grammar> [you@localhost kgp]$ cat binary.xml | python kgp.py -g -
![]()
10110001
![]() |
正如您在第 9.1 节“深入” 中看到的,这将打印一个由八个随机位组成的字符串,0 或 1。 |
![]() |
这只是简单地打印出 binary.xml 的全部内容。(Windows 用户应使用 type 而不是 cat。) |
![]() |
这将打印 binary.xml 的内容,但“|”字符(称为“管道”字符)表示内容不会打印到屏幕上。相反,它们将成为下一个命令的标准输入,在本例中,该命令调用您的 Python 脚本。 |
![]() |
您没有指定模块(如 binary.xml),而是指定了“-”,这会导致您的脚本从标准输入而不是磁盘上的特定文件加载语法。(有关如何实现这一点的更多信息,请参见下一个示例。)因此,效果与第一个语法相同,在第一个语法中,您直接指定了语法文件名,但请考虑这里的扩展可能性。您可以运行一个动态生成语法的脚本,而不是简单地执行 cat binary.xml,然后您可以将其通过管道传输到您的脚本中。它可以来自任何地方:数据库、某些语法生成元脚本,等等。关键是您根本不需要更改 kgp.py 脚本就可以合并任何这些功能。您需要做的就是能够从标准输入中获取语法文件,并且您可以将所有其他逻辑分离到另一个程序中。 |
那么,当语法文件为“-”时,脚本如何“知道”从标准输入读取?这不是魔术;这只是代码。
def openAnything(source): if source == "-":import sys return sys.stdin # try to open with urllib (if source is http, ftp, or file URL) import urllib try: [... snip ...]
![]() |
这是来自 toolbox.py 的 openAnything 函数,您之前在“10.1. 抽象化输入源”中检查过。您所做的只是在函数开头添加了三行代码,用于检查源是否为“-”。如果是,则返回 sys.stdin。真的,就是这样!请记住,stdin 是一个具有 read 方法的类文件对象,因此其余代码(在调用 openAnything 的 kgp.py 中)一点也没有改变。 |
<< 脚本和流 |
| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | |
缓存节点查找 >> |