stdout, stdin, stderr的区别

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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值