天天看點

Python基礎教程講解——print輸出重定向介紹redirection start...redirection end臨時把标準輸出重定向到一個檔案,然後再恢複正常

本期的Python基礎教程給大家講print輸出相關知識點,敲黑闆聽課了!

Python中調試程式使用最多的是print(),在使用print()列印時事實上是調用了 sys.stdout.write()。不過print在把内容列印到控制台後,追加了一個換行符(linefeed)。以下例程中,print和sys.stdout.write()是等價的:

sys.stdout.write('Hello Worldn')

print('Hello World')

在Python中, sys.stdin、sys.stdout和sys.stderr分别對應解釋器的标準輸入、标準輸出和标準出錯流。在程式啟動時,這些對象的初值由sys.stdin、sys.__stdout__和sys.__stderr__儲存,比便于恢複标準流對象。如下所示:

print(sys.stdout) # <_io.TextIOWrapper name='' mode='w' encoding='UTF-8'>

print(sys.stdin) # <_io.TextIOWrapper name='' mode='r' encoding='UTF-8'>

print(sys.stderr) # <_io.TextIOWrapper name='' mode='w' encoding='UTF-8'>

print(sys.__stdout__) # <_io.TextIOWrapper name='' mode='w' encoding='UTF-8'>

print(sys.__stdin__) # <_io.TextIOWrapper name='' mode='r' encoding='UTF-8'>

print(sys.__stderr__) # <_io.TextIOWrapper name='' mode='w' encoding='UTF-8'>

如果我們要把内容重定向到文本中去時,該如何操作呢?我們先看下普通的文本對象和标準輸出對象的差別。如下所示:

print(dir(sys.stdout))

"""

['_CHUNK_SIZE', '__class__', '__del__', '__delattr__', '__dict__', '__dir__', '__doc__',

'__enter__', '__eq__', '__exit__', '__format__', '__ge__', '__getattribute__', '__getstate__',

'__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__lt__',

'__ne__', '__new__', '__next__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__',

'__sizeof__', '__str__', '__subclasshook__', '_checkClosed', '_checkReadable', '_checkSeekable',

'_checkWritable', '_finalizing', 'buffer', 'close', 'closed', 'detach', 'encoding', 'errors',

'fileno', 'flush', 'isatty', 'line_buffering', 'mode', 'name', 'newlines', 'read', 'readable',

'readline', 'readlines', 'reconfigure', 'seek', 'seekable', 'tell', 'truncate', 'writable', 'write',

'write_through', 'writelines']

with open('redirect.txt', 'w') as f:

print(f) # <_io.TextIOWrapper name='redirect.txt' mode='w' encoding='cp1252'>
print(dir(f))
"""
['_CHUNK_SIZE', '__class__', '__del__', '__delattr__', '__dict__', '__dir__', '__doc__', 
'__enter__', '__eq__', '__exit__', '__format__', '__ge__', '__getattribute__', '__getstate__', 
'__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__lt__', 
'__ne__', '__new__', '__next__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', 
'__sizeof__', '__str__', '__subclasshook__', '_checkClosed', '_checkReadable', '_checkSeekable', 
'_checkWritable', '_finalizing', 'buffer', 'close', 'closed', 'detach', 'encoding', 'errors', 
'fileno', 'flush', 'isatty', 'line_buffering', 'mode', 'name', 'newlines', 'read', 'readable', 
'readline', 'readlines', 'reconfigure', 'seek', 'seekable', 'tell', 'truncate', 'writable', 'write', 
'write_through', 'writelines']
"""           

可見兩者都屬于檔案對象,其中所包含的方法也都相同,比如write、read等等。是以,如果把檔案對象的引用指派給sys.stdout,那麼print調用的即為檔案對象的write方法,這樣就實作了重定向。其實在之前的Python基礎教程中有跟大家講古。代碼如下所示:

sys.stdout = f
print("Hello World")           

重定向後,print列印的内容就從控制台搬到了文本上了,如下所示:

Python基礎教程講解——print輸出重定向介紹

如果隻是臨時向檔案中列印内容,之後仍然會在控制台上列印的話,應該先将原始的控制台引用對象儲存下來,之後将該引用恢複到sys.stdout中。如下所示:

console = sys.stdout

redirection start

...

redirection end

sys.stdout = console

以上的實作方法并不優雅,典型的實作如下所示:

臨時把标準輸出重定向到一個檔案,然後再恢複正常

oldstdout = sys.stdout
sys.stdout = f
try:
    help(__import__)
finally:
    sys.stdout = oldstdout           

print("Hello World")

接下來介紹Pyhton上下文管理器redirect_stdout實作重定向的方法。contextlib.redirect_stdout在Python 3.4加入。如下所示:

with contextlib.redirect_stdout(f):
    help(pow)           
Python基礎教程講解——print輸出重定向介紹redirection start...redirection end臨時把标準輸出重定向到一個檔案,然後再恢複正常

當然,其實redirect_stdout的内在實作邏輯也僅是儲存控制台的引用,而後恢複如此而已。于是我們可以實作自己的redirect_stdout上下文管理器。如下所示:

@contextlib.contextmanager

def redirect_stdout(fileobj):

oldstdout = sys.stdout
sys.stdout = fileobj
try:
    yield fileobj
finally:
    sys.stdout = oldstdout
           

def redirect4():

with open('redirect.txt', 'w') as f:
    with redirect_stdout(f):
        help(pow)

print("Hello World")           

更多的Python基礎教程也會繼續更新,大家有想學想看的内容也可以留言,我會整理出相關文章哈!