Python Shell 中敲擊方向鍵顯示「^[[C^[[D」,原因是什麼?如何修復?

系統環境: OS X 10.8

Python: version 2.7.5, built from source, isolated by virtualenv.

問題描述: 通過"source bin/active"進入virtualenv環境後, 在Python Shell中敲擊方向鍵, 會出現">&>&>^[[C^[[D"等字樣. 但在非virtualenv環境的Python Shell(系統自帶版本, 源碼構建版本)中並不會出現這種現象. 我想知道為什麼會出現這樣的問題, 以及如何修復.

PS: 小白問題, 才疏學淺, google無果後上來求教.

====================================================

Stackoverflow上有類似的問題:

  • input - Python shell: Arrow keys do not work on remote machine
  • How to repeat last command in python interpreter shell?

Python Doc: 2. Using the Python Interpreter

====================================================

感謝@吳濤的回答, 我基本知道從哪裡入手解決這個問題了, 但是我的情況可能更加複雜一點, 原因可能與codecs這個package有關, 問題是在使用這個庫之後才出現的, 與 python - Arrow keys in Putty returning [[A^ [[D^ [[B^ instead of moving the cursor 的描述可能有關聯.


&> 我想知道為什麼會出現這樣的問題

那你有沒有想過,為什麼 terminal 那麼大,你卻只能從一個角落裡開始可憐巴巴地一次輸入一行命令么……其實兩者的答案如果尋根問底的話——假定你來知乎問問題是想尋根問底——是一樣的。

一九七〇年代廉價的電子圖像顯示器出現之前,大型機的終端通常使用電傳打字機(teleprinter)來跟用戶交互;電傳打字機的輸出印在紙上,用戶輸入的字元就像打字機一樣是刪不掉的,而且用戶輸入什麼就會立刻傳給伺服器;後來有了以電子顯示器為輸出設備的終端,一開始也只能一個字元一個字元地給服務端發信息,到七十年代末能一次給伺服器發送一整行信息的「智能」終端才成為主流。此時鍵盤上才有了現代電腦用戶覺得司空見慣(拿鍵盤當鋼琴使的 HHKB Pro 2 用戶請扭過頭去)的方向鍵。而按下方向鍵給終端發送的是控制游標移動的命令,這些命令最初的表示方法是轉義字串(escape sequence),也就是「我先說幾個字元,說完這幾個字元之後再說的那個字元請不要當作字面意思理解」。這個字元在 ANSI 標準裡面排行第 27(0x1B),它是個看不見的字元,一般寫「&」來代表。而 ANSI 的終端機標準裡面,游標上、下、右、左移動的指令分別規定為 &[A,&[B,&[C,&[D,其中方括弧跟字母之間還可以插入一個數字來表示要移動幾位。

你現在使用的終端模擬器,不管是 Terminal.app 還是 iTerm 2,其實都是在用軟體模擬當年用硬體實現的終端,並且還在底層幫你把按下的方向鍵轉化為能夠用來移動游標的特定轉義字串。編一個 C 程序,main 里只有一行 getchar(); 編譯運行(或者先在 iTerm 里按 ctrl + v ),再按上下右左,屏幕上都會顯示 ^[[A ^[[B ^[[C ^[[D。其中 ^[ 就代表 esc 字元(因為 ctrl + [ 輸入的字元是 0x1B)。

而無論 bash、zsh 還是 OS X 系統自備的 Python shell,其實都是在底層將你按下方向鍵所產生的這三個字元按照 ANSI 標準理解為你要移動游標,並移動游標。這種「把三個字元按照 ANSI 標準理解為你要移動游標」,或者叫做「line editing」,的功能是如此常用,以至於人們寫了專門的程序庫來做這件事,它叫做 The GNU Readline Library。

但問題在於,readline 採用 GPL v3 授權,這一授權要求所有使用 readline 的程序必須開源。在版權法執行得比我國好的國家裡,這是個嚴重的問題,OS X 裡面也就因此沒有 readline 庫。所以,如果你不去弄一份 GNU Readline,&virtualenv&(註:此處我把 pythonz 和 virtualenv 弄混了。virtualenv 並不能編譯 Python,只是創建一份隔離開來的 Python 運行環境)你自己編譯的 Python shell 就沒有 line editing 功能;而如果你在創建虛擬環境的時候指定了這一自行編譯的版本作為該環境的 Python,那麼當你切換到那個環境的時候就會出現這樣的問題。為了在不帶 GNU Readline 的系統下給 Python 程序提供 line editing 功能,Python 提供了https://pypi.python.org/pypi/readline 模塊,以內嵌 GNU readline 庫。更多信息可以讀它的文檔。

那麼蘋果 OS X 自帶的 Python shell 是怎樣實現 line editing 的呢?是用 BSD 授權的 Editline Library (libedit) 。

此外,也有可能是 virtualenv 沒有正確地處理獨立環境里的庫——在 https://pypi.python.org/pypi/virtualenv 一頁上搜尋「readline」,可以看到不少都和 OS X 有關,所以應該確定自己在使用 virtualenv 的最新版本。

而 readline 提供的功能,除去按方向鍵移動游標,還包括比如 ctrl + a 到行首、ctrl + e 到行尾、alt + f 前進一個單詞、alt + b 後退一個單詞之類;如果覺得 Emacs 討厭,還可以轉用 vi key-binding。如何才能挖掘出 readline 的全部功能,就留給讀者做為習題好了。

&> 以及如何修復

easy_install readline

(不,別用pip)


安裝yum -y install readline-devel,然後在重新編譯python


光是裝readline不行的吧,還得重新編譯python一次


請問誰知道非root用戶怎麼辦(?ω?)


我在使用PYTHON3的時候也出現了這樣的問題,按照樓上的解釋,安裝了這個包libreadline-dev,我的是Description: Ubuntu 15.10,然後重新下載python3 編譯安裝,就沒有這個問題了,方向鍵可以用了。謝謝樓上的各位。


推薦閱讀:

為什麼python代碼有時候在命令行下和Python Shell中執行的結果不一樣呢 ?
Python 曾經開發過哪些了不起的程序或遊戲?
Python分析中文文字有哪些方法,那些庫?
會了django還有必要學flask嗎?
學習python有什麼好的視頻?

TAG:Python | Linux | Shell編程開發 |