В bash я могу предотвратить сохранение команды в истории bash, поставив перед ней пробел. Я не могу использовать этот метод в ipython. Как сделать эквивалент в ipython?
Как я могу избежать сохранения команды в истории ipython?
Ответ 1
Замечание об устаревании: это было написано для IPython 4.0.1
. Начиная с v5, IPython больше не использует readline
.
Отсутствие запаса, может быть добавлено или обработано.
В IPython существует два типа истории:
-
readline
история. Он доступен со специальными комбинациями клавиш/клавиш (вверх/вниз, Ctrl-R и т.д.). Сохраняет только введенные строки (с<Enter>
) на консоли (или вpyreadline
, вставленные из буфера обмена). IPython полагается на локальную реализацию Pythonreadline
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
с помощью флажков, проверяющих флажки в соответствующих объектах, и настраиваемая магическая команда, которая устанавливает/переключает их. трюк.
- readline: в публичном API нет соответствующей записи, поэтому она специфична для реализации. Например. для
-
автоматически удаляет
evidenceввод/вывод из истории сразу после выполнения. Это можно сделать с помощью префиксной магии.- IPython:
HistoryManager
не имеет средств для удаления записей (ни из базы данных, ни из переменных). Увы, необходимо взломать БД вручную/заменить запасHistoryManager
. Также обратите внимание, что класс имеет дополнительный кешHistoryManager.db_cache_size
(по умолчанию отключен). - readline:
remove_history_item(index)
находится в API. Вам нужно знать количество строк на входе.
- IPython:
В качестве альтернативы, если вам требуется только ввести пароль, рассмотрите другие способы, которые не повторяют пароль на экране (таким образом, не делая его частью истории консоли):
-
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 исчезла.
Вот несколько документов, которые я просмотрел