开头说两句
StringIO实际上就是在内存中读写str类型的数据。- 在这个
demo中还会用到关于sys库的输出stdout模块。(拦截stdin和stderr也是同理)stdin用于所有交互式输入(包括调用 input());stdout用于输出print()和表达式语句以及提示input();stderr用于将解释器自己的提示及其错误消息输出。
进入 demo
-
demo 代码
import sys from io import StringIO class ConsoleOutputRedirect: """ Wrapper to redirect stdout or stderr """ def __init__(self, fp): self.fp = fp def write(self, s): self.fp.write(s) def writelines(self, lines): self.fp.writelines(lines) def flush(self): self.fp.flush() stdout_redirect = ConsoleOutputRedirect(sys.stdout) def print_something(): # should be print something but it shouldn`t print("Hello Leo!") def block_output(): # Block Console stdout stdout_redirect.fp = StringIO() temp_stdout, sys.stdout = sys.stdout, stdout_redirect # Core Method print_something() # Swap sys.stdout sys.stdout = temp_stdout # Block output print("Today is Good Weather, {}".format(stdout_redirect.fp.getvalue())) if __name__ == '__main__': block_output() -
运行完这段代码后会惊奇的发现控制台中只输出了
Today is Good Weather, Hello Leo!。(这就是拦截的魔力)
demo 讲解
- 大体的讲解:
- 实际上就是将需要拦截部分的
sys.stdout(即需要拦截print的内容) 通过自定义StringIO的方式进行截获,最终再通过其他方式将拦截内容呈现出来即可。
- 实际上就是将需要拦截部分的
- 讲解点:
- 1、首先得了解 Python 中
print这个函数在输出的过程中干了哪些内容。- 官方文档 中也提到,实际上
print在输出的过程使用的就是输入输出流。print中的内容通过write stream的方式写入到str中。而正好在 Python 中管理IO的类就是_IOBase, 也是StringIO的父类。
- 官方文档 中也提到,实际上
- 2、拦截输出的核心是基于
StringIO的这个类读取输出的内容,因此就需要了解StringIO关于输出部分的核心方法。StringIO, 以及拦截所需要的方法。- 拦截过程前首先得让
print或者叫sys.stdout的内容赋予给我们代码中的一个变量,这样我们才能对这个输出内容进行拦截或者叫 hack。 - 拦截之后,将空的输出流赋给
sys.stdout即可,代码中是在拦截之前将一个未使用的sys.stdout输出流赋给了一个临时变量,最后再通过StringIO的getvalue从我们自定义的StringIO对象中取出我们需要的内容就完成了。
- 拦截过程前首先得让
- 3、实际上就是拦截前和拦截后两部分的
sys.stdout的交换。(大体上可以理解成两个变量交换[略微不严谨的理解])
- 1、首先得了解 Python 中