2016-01-29 67 views
10

在bash中,我可以通過在前面放置一個空格來防止命令被保存到bash歷史中。我不能在ipython中使用這個方法。我將如何做ipython中的等價物?如何避免在ipython歷史中存儲命令?

+0

相對。 ated:https://stackoverflow.com/questions/19606275/ipython-how-to-wipe-ipythons-history-selectively-securely – ShreevatsaR

回答

3

過時注意:這是爲IPython 4.0.1寫的。 As of v5, IPython no longer uses readline


沒有庫存的方式,可以添加或解決。

有兩種類型的歷史,在IPython中:

  • readline歷史。它有特殊的鍵/組合鍵(上/下,Ctrl-R等)。僅在控制檯上存儲輸入行(與<Enter>)(或從剪貼板粘貼pyreadline)。 IPython依賴於Python readline API的本地實現,它沒有「不添加」功能,並且通常會將每一行添加到歷史記錄中。
    IPython有一個緩解這種情況的工具,IPython.core.interactiveshell.ReadlineNoRecord,一個上下文管理器,可以創建歷史記錄並恢復它。從ipython 4.0.1開始,它僅被%run魔術使用,以避免將腳本交互輸入添加到歷史記錄中。

  • IPython的歷史。它保存在數據庫和自動變量中。它包含完整的輸入(readline分別抓取每行<Enter>'ed線對於多行)和輸出。在HistoryManager.store_inputs()(用於輸入)和HistoryManager.store_output()(用於輸出)中執行保存,該輸出從InteractiveShell.run_cell調用並受其參數store_history的控制。後者又被稱爲TerminalInteractiveShell.interactstore_history=True

有兩種方法來解決這個問題爲任一層:

  • 防止將輸入在首位。這不能用命令前綴的魔術來完成,只能使用一個作爲單獨命令運行並切換標誌的魔術。這是因爲,正如你所看到的,當魔術命令得到控制時,當前輸入已經被存儲。

    • readline:公共API中沒有相關條目,因此它是特定於實現的。例如。對於pyreadline,添加使用pyreadline.modes.basemode.BaseMode.add_history()完成。模式對象可以被訪問爲get_ipython().readline.rl.mode
    • 裝飾run_celladd_history與包裝檢查相應對象中的標誌和custom magic command設置/切換他們應該做的伎倆。
  • 自動刪除證據執行後立即輸入/輸出歷史記錄。這可以用前綴魔術來完成。

    • IPython:HistoryManager沒有任何設施可以刪除條目(既不從DB也不從變量)。唉,手動破解DB /更換股票HistoryManager是必要的。另請注意,該類有一個可選緩存HistoryManager.db_cache_size(默認情況下禁用)。
    • readline:remove_history_item(index)在API中。您需要知道輸入中的行數。

另外,如果你只需要此輸入密碼,可以考慮其他方式不上屏幕顯示密碼(因此沒有把它控制檯歷史的一部分):

+0

1. _「防止首先添加輸入,這不能通過命令前綴的魔術來完成,只能使用作爲單獨命令運行的命令並切換標誌」_什麼是單獨命令的示例切換標誌以防止添加輸入? 2. _使用包裝檢查相應對象中的標誌並設置run_cell和add_history以及設置/切換它們的自定義魔術命令應該做到這一點._您可以添加示例嗎? – ShreevatsaR

+0

@ShreevatsaR 0)參見陳舊筆記; 1)'%toggle','your_command','%toggle'; 2)這意味着用它們周圍的包裝來代替這些功能;一個例子超出了答案的範圍,這對任何具有體面專業知識的人都應該清楚。 –

4

我想我終於明白了這一點。這種方法並不真正'阻止'ipython記錄歷史,但實際上刪除的歷史記錄。但我認爲這仍然是實現這一目標的好方法。

ipython的歷史記錄存儲在一個sqlite數據庫文件在$(ipython locate)/profile_default/history.sqlite

數據庫表歷史有四列:會議source_raw會話列提供了當前會話的session_id,它可以通過ipython中的方法獲得:get_ipython().history_manager.hisdb.get_last_session_id()ipython列只是行號。

那麼我現在要做的是我要去ipython環境內刪除在數據庫中這樣記載:

1)歷史db對象可以使用get_ipython().history_manager.db得到ipython

hismgr = get_ipython().history_manager 

2)獲取會話ID:

session_id = hismgr.get_last_session_id() 

3)刪除了與line_id(假設它是111在這裏)和session_id

hismgr.db.execute('DELETE FROM history WHERE line={0} and session={1}'.format(111, session_id)) 

4)InOut數組列表也是那種喜歡歷史,但它存儲在內存中,因此它可以被掃或重寫樣可變保守黨線。

In[111]=Out[111]='' 

要「防止被保存到IPython的歷史命令」,是指刪除線的歷史記錄在數據庫和重寫退房IPython的環境陣列。我們可以將這四條線合併爲一條,爲所有人做一次這項工作。 這裏,如果我們想刪除線128爲例

In [127]: history -l 3 -n 
124: history -l 3 -n 
125: hismgr = get_ipython().history_manager; session_id = hismgr.get_last_session_id();hismgr.db.execute('DELETE FROM history WHERE line={0} and session={1}'.format(123, session_id)) 
126: history -l 3 -n 

In [128]: passwd='123456' 

In [129]: hismgr = get_ipython().history_manager; session_id = hismgr.get_last_session_id();hismgr.db.execute('DELETE FROM history WHERE line={0} and session={1}'.format(128, session_id));In[128]=Out[128]=''; 
Out[129]: <sqlite3.Cursor at 0x7f8dce3dae30> 

In [130]: history -l 3 -n 
126: history -l 3 -n 
127: history -l 3 -n 
129: hismgr = get_ipython().history_manager; session_id = hismgr.get_last_session_id();hismgr.db.execute('DELETE FROM history WHERE line={0} and session={1}'.format(128, session_id));In[128]=Out[128]=''; 

歷史線128消失了。

下面是一些我的文檔通過

IPython.core.history.HistoryManager

python-sqlite3

+0

這實際上並不「避免在歷史中存儲一行」,而是將其從歷史中刪除事後。 –

+0

@ivan_pozdeev我知道。但是我通過ipython文件讀取,並且找不到真正的「防止命令保存到歷史記錄」的方式,所以我出來說如果我刪除這行會做同樣的工作。 – realhu