Как я могу избежать сохранения команды в истории ipython?

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

Ответ 1

Замечание об устаревании: это было написано для IPython 4.0.1. Начиная с v5, IPython больше не использует readline.


Отсутствие запаса, может быть добавлено или обработано.

В IPython существует два типа истории:

  • readline история. Он доступен со специальными комбинациями клавиш/клавиш (вверх/вниз, Ctrl-R и т.д.). Сохраняет только введенные строки (с <Enter>) на консоли (или в pyreadline, вставленные из буфера обмена). IPython полагается на локальную реализацию Python readline API, который не имеет функции "не добавлять" и обычно добавляет каждую строку к истории.
    У IPython есть возможность облегчить это, IPython.core.interactiveshell.ReadlineNoRecord, менеджер контекста, который создает моментальный снимок истории, а затем восстанавливает его. Начиная с IPython 4.0.1, он используется только магией %run, чтобы избежать добавления интерактивного ввода script в историю.

  • История IPython. Он сохраняется в БД и автоматических переменных. Он содержит полные входы (readline захватывает каждую строку <Enter> 'ed отдельно для многострочных) и выходы. Сохранение реализовано в 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 с помощью флажков, проверяющих флажки в соответствующих объектах, и настраиваемая магическая команда, которая устанавливает/переключает их. трюк.
  • автоматически удаляет evidence ввод/вывод из истории сразу после выполнения. Это можно сделать с помощью префиксной магии.

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

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

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

Ответ 2

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

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

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

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

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

hismgr = get_ipython().history_manager   

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

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) Список массивов In и Out также похож на историю, но он хранится в памяти, поэтому он может быть развернут или переписать как переменную.

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