stdin, stdout,stderr的中文名字分别是标准输入,标准输出和标准错误。
当一个用户进程被创建的时候,系统会自动为该进程创建三个数据流, 一个程序要运行,需要有输入、输出,如果出错,还要能表现出自身的错误。这就是要从某个地方读入数据、将数据输出到某个地方,这就够成了数据流。
因此,一个进程初期所拥有的这三个数据流即为标准输入、标准输出和标准错误,分别用stdin, stdout, stderr来表示。这3个文件分别为标准输入(stdin)、标准输出(stdout)、标准错误(stderr)。大多数环境中,stdin指向键盘,stdout、stderr指向显示器。之所以使用stderr,是因为一般来讲,若因某种原因造成其中一个文件无法访问,相应的诊断信息要在该程序运行输出信息的末尾才能打印出来。当输出到屏幕时,这种处理方法尚可接受,但如果诊断信息输出到一个文件或通过管道输出到另一个程序时,就无法接受了。若有stderr存在,即使对标准输出进行了重定向,也只有stdout的信息会写入重定向文件,而stderr中的输出还是显示在屏幕上。
sys.stdin 介绍
sys.stdin提供了read()和readline()函数,如果想按一行行来读取,可以考虑使用它:
import sys
line = sys.stdin.readline()
while line:
print line,
line = sys.stdin.readline()
注意:如果没有数据,io会被堵塞,所以可以对标准输入做数据检查(Linux):
···
import sys
import select
if select.select([sys.stdin], [], [], 0.0)[0]:
help_file_fragment = sys.stdin.read()
else:
print(“No data”, file=sys.stderr)
sys.exit(2)
···
此外,python还提供input()函数可以进行数据输入,但两者有区别,input()会把末尾的‘\n’忽略:
>>> a = input("请输入一个数字:")
请输入一个数字:20
>>> a
而stdin.readline()默认输入的格式是字符串,如果输入的是int,float类型则会强制转换成字符串类型,且会将标准输入全部获取,包括末尾的’\n’。
sys.stdin 还可以与print合用产生input的效果:
import sys
print('Please input your name: ')
name = sys.stdin.readline()
print('Hello ', name)
输出结果:
Please input your name:
Hello
这里可以看到,尽管在print('Hello ', name)里,name在后面,但是在显示的时候会出现在前面。
sys.stdout与sys.stderr 介绍
在默认情况下,stdout是行缓冲的,他的输出会放在一个buffer里面,只有到换行的时候,才会输出到屏幕。stderr是不带缓冲的,这使得出错信息可以直接尽快地显示出来。
sys.stdout 还可将标准输出重新定向到指定文件:
import sys
sys.stdout = open('log', 'a')
b = print('haha', file=sys.stdout)
运行代码后打印信息不会在屏幕上显示,而是会写到log文件中
sys.stderr 则可将标准错误信息重定向输出到错误文件中:
import sys
sys.stdout = open('errlog', 'a')
b = print('haha', file=sys.stdout)
运行代码后错误信息不会在屏幕上显示,会写入到errlog文件中
在linux中可以不用指定sys的stdout和stderr文件,若运行:
python test.py >log 2>errlog
这样打印信息会在log文件中,错误信息会展示到errlog文件中。这里的2表示标准错误信息流,>errlog表示将结果打印到errlog文件中。
此外,我们还可以结合logging模块的操作通过指定handler来控制屏幕信息输出:
#test.py
import logging
import sys
logger1=logging.getLogger("logger1")
handler1 = logging.StreamHandler(sys.stderr)
formatter1 = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
handler1.setFormatter(formatter1)
logger1.addHandler(handler1)
logger2=logging.getLogger("logger2")
formatter2 = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
handler2 = logging.StreamHandler(sys.stdout)
handler2.setFormatter(formatter2)
logger2.addHandler(handler2)
logger2.setLevel(level=logging.INFO)`
logger1.info("not output because of level")
logger1.warning("output in red")#标准错误输出在notebook中输出是红色的。
logger2.info("output in white")
logger2.warning("output in white")#标准正常输出是白色的。
输出结果为:
2022-07-28 15:25:56,570 - logger1 - WARNING - output in red
2022-07-28 15:25:56,575 - logger2 - INFO - output in white
2022-07-28 15:25:56,577 - logger2 - WARNING - output in white
如果进行重定向,python test.py >log 2>errlog,则第一条logger1的输出结果存入errlog文件,其余logger2的输出结果存入log文件。
sys.stdout.write方法
sys.stdout还有一个write方法,调用的是 file 对象的 write 方法,区别是 file 对象的 write 方法把字符写入到文件中,sys.stdout.write 方法把字符写入到标准输出中,也就是控制台。这一点上与print()方法类似,但是stdout.write 默认不换行,print 默认换行。
import sys
print('print 默认换行')
sys.stdout.write('stdout.write 默认不换行')
print('+++++++++')
输出结果:
print 默认换行
stdout.write 默认不换行+++++++++
因此stdout.write 需配合 \n 换行符实现换行功能:
sys.stdout.write('str \n')
print也可以实现不换行:
print('str', end='')
此外,print 几乎可以打印所有的对象,而 stdout.write 只能接受 str 类型。
import sys
class name():
def __str__(self):
return 'Citizen_Wang'
a = name()
print(a)
print(type(a))
sys.stdout.write(a)
此脚本会报错:
TypeError: write() argument must be str, not name
解决方法:
sys.stdout.wirte(str(a))
sys.stdout还可以与print结合使用:
import sys
file = sys.stdout # 存储原始的输出对象
sys.stdout = open('1.txt', 'w') # 重定向所有的写入内容到 1.txt 文件
print('Citizen_Wang') # 写入到 1.txt 文件中
print('Always fall in love with neighbours') # 继续写入到文件中
sys.stdout.close() # 其实就是 open 文件之后的关闭
sys.stdout = file # 将 print 命令的结果返回给控制台
print('输出信息返回在控制台') # 该信息会在控制台也显示
以上代码会在当前目录下创建了一个 1.txt 文件,内容如下:
Citizen_Wang
Always fall in love with neighbours