2016-01-29 1 views
10

В bash я могу предотвратить сохранение команды в истории bash, поставив перед ней пробел. Я не могу использовать этот метод в ipython. Как сделать эквивалент в ipython?Как я могу избежать сохранения команды в истории ipython?

+0

Rel 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> «отдельную линию отдельно для многострочных) и выходы. Сохранение реализовано в HistoryManager.store_inputs() (для входов) и HistoryManager.store_output() (для выходов), которое вызывается от InteractiveShell.run_cell и определяется его аргументом store_history. Последнее, в свою очередь, называется от TerminalInteractiveShell.interact с store_history=True.

Есть два способа решения проблемы для любого слоя:

  • предотвратить добавление вход в первую очередь. Это невозможно сделать с помощью магии, предваряемой командой, только с той, которая запускается как отдельная команда и переключает флаг. Это потому, что, как вы видели, текущий вход уже был сохранен к тому времени, когда волшебная команда получит контроль.

    • readline: в публичном API нет соответствующей записи, поэтому она специфична для реализации. Например. для pyreadline, добавление выполняется с помощью pyreadline.modes.basemode.BaseMode.add_history(). Объект режима доступен как get_ipython().readline.rl.mode.
    • Отделка run_cell и add_history с обертками, проверяющими флажки в соответствующих объектах и ​​custom magic command, которые устанавливают/переключают их, должны делать трюк.
  • автоматически удаляет доказательства ввод/вывод из истории сразу после выполнения. Это можно сделать с помощью префиксной магии.

    • IPython: HistoryManager не имеет средств для удаления записей (ни от БД, ни от переменных). Увы, необходимо взломать БД вручную/заменить запас HistoryManager. Также обратите внимание, что класс имеет дополнительный кеш HistoryManager.db_cache_size (по умолчанию отключен).
    • readline: remove_history_item(index) находится в API. Вам нужно знать количество строк на входе.

В качестве альтернативы, если вам требуется только это вводить пароли, рассмотреть другие способы, которые не повторяют пароль на экране (таким образом, не делает его частью истории консоли):

  • getpass.getpass()
  • хранить его в другом месте (например, в файл конфигурации только для чтения вами)
+0

1. _ «предотвратить добавление ввода в первую очередь. Этого нельзя сделать с помощью магии, предваряемой командой, только с той, которая запускается как отдельная команда и переключает флаг« _ что является примером отдельной команды переключить флаг, чтобы предотвратить добавление ввода? 2. _Декация run_cell и add_history с обертками, проверяющими флажки в соответствующих объектах, и пользовательская команда магии, которая устанавливает/переключает их, должна делать трюк. Вы можете добавить пример? – ShreevatsaR

+0

@ShreevatsaR 0) см. Устаревание; 1) '% toggle',' your_command', '% toggle'; 2) это означает замену этих функций обертками вокруг них; пример выходит за рамки ответа, это должно быть понятно любому, кто имеет приличную экспертизу. –

4

Думаю, я наконец понял это. Этот метод не «предотвращает» ipython для записи истории, а фактически удаляет историю записи. Но я думаю, что это хороший способ достичь этой цели.

История ipython хранится в базе данных . файл в $(ipython locate)/profile_default/history.sqlite.

Таблица базы данных История имеет четыре колонки: сессии, линии, источник и source_raw. В столбце представлен для текущего сеанса session_id, его можно получить с помощью метода в ipython: get_ipython().history_manager.hisdb.get_last_session_id() в ipython. Колонка - это просто номер строки.

Так что я собираюсь сделать, это я собираюсь удалить эту запись в базе данных в ipython среды:

1) Объект истории дб можно получить с помощью get_ipython().history_manager.db в ipython

hismgr = get_ipython().history_manager 

2) получить идентификатор сессии:

session_id = hismgr.get_last_session_id() 

3) удалить Hist ORY линия с line_id (предположим, что это 111 здесь) и session_id

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

4) Перечень In и Out массив также вид, как история, но она хранится в памяти, так что это может быть подметать или перезаписать как переменную ,

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

Чтобы «предотвратить команду сохранения на IPython истории», означает удаление истории записи в строке в базе данных и и переписать В и Out массива в 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

Смежные вопросы