天天看點

Python IDLE reload(sys)後無法正常執行指令的原因

通常大多數人執行reload(sys)這條語句其實僅僅是為了能夠修改Python的預設字元集,也就是能夠調用sys.setdefaultencoding()。但是如果在IDLE中執行reload(sys),就會導緻接下來無法正常執行任何指令。

起初遇到這個問題也是束手無策,後來無意間在stackoverflow上看到有人說到了這個問題。原來是因為IDLE作為一個GUI Shell環境,在啟動初始化過程中,會設定特定的标準輸入、标準輸出和标準錯誤輸出,使得輸入和輸出都在IDLE的GUI Shell中,可以在IDLE中通過如下方式檢視:

>>> import sys
>>> print sys.stdin
<idlelib.PyShell.PseudoInputFile object at 0x00000000027AF2E8>
>>> print sys.stdout
<idlelib.PyShell.PseudoOutputFile object at 0x00000000027AF320>
>>> print sys.stderr
<idlelib.PyShell.PseudoOutputFile object at 0x00000000027AF358>
>>> 
           

而如果手動執行了reload(sys)以後,sys子產品的這三個變量将會被重置,導緻輸出無法顯示在IDLE。是以解決方案很簡單,隻需要在reload之前把這三個變量都複制一份,reload之後再恢複回來就行了:

>>> stdi,stdo,stde=sys.stdin,sys.stdout,sys.stderr
>>> reload(sys)
>>> sys.stdin,sys.stdout,sys.stderr=stdi,stdo,stde
>>> print sys.stdout
<idlelib.PyShell.PseudoOutputFile object at 0x00000000027AF320>
>>> 
           

細心的人可能會想到,reload(sys)之後,如果标準輸入、标準輸出和标準錯誤輸出都不起作用了,那麼relaod(sys)後面那一句sys.stdin,sys.stdout,sys.stderr=stdi,stdo,stde怎麼能夠執行呢?是以其實reload(sys)之後、恢複之前,标準輸入還是可以正常工作的,可以通過如下代碼來檢驗:

>>> reload(sys)
>>> sys.stdout=stdo
>>> print sys.stdin
<open file '<stdin>', mode 'r' at 0x0000000001CAB030>
>>> print sys.stdout
<idlelib.PyShell.PseudoOutputFile object at 0x00000000027AF320>
>>> print sys.stderr
<open file '<stderr>', mode 'w' at 0x0000000001CAB150>
>>> 
           

是以問題就解決了,但是必須要強調:

千萬不要輕易使用reload(sys),除非你完全清楚這麼做帶來的結果!僅僅為了能夠重新設定Python的預設編碼就執行reload(sys)更是非常不明智的行為!

Python的設計者故意在Python初始化完成以後删除sys子產品裡面的setdefaultencoding()方法,就是為了不讓在運作時随意更改Python預設編碼,以免出現一些未知的問題。事實上,關于編碼問題,完全有别的更可靠的方法解決。