В bash я могу предотвратить сохранение команды в истории bash, поставив перед ней пробел. Я не могу использовать этот метод в ipython. Как бы я сделал эквивалент в ipython?
как я могу избежать сохранения команды в истории ipython?
Ответы (3)
Примечание об устаревании: это было написано для IPython 4.0.1
. Начиная с версии 5 IPython больше не использует readline
.
Нет стандартного способа, можно добавить или обойти.
В IPython есть два вида истории:
readline
история. Он доступен с помощью специальных клавиш/комбинаций клавиш (вверх/вниз, Ctrl-R и т.д.). Сохраняет только строки, введенные (с<Enter>
) на консоли (или, вpyreadline
, также вставленные из буфера обмена). IPython опирается на локальную реализацию Pythonreadline
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: there's no relevant entry in the public API, so it's implementation-specific. E.g. for
pyreadline
, adding is done withpyreadline.modes.basemode.BaseMode.add_history()
. The mode object is accessible asget_ipython().readline.rl.mode
. - Украшаем
run_cell
иadd_history
обертками, проверяющими флаги в соответствующих объектах, и пользовательской магической командой то, что устанавливает/переключает их, должно помочь.
- readline: there's no relevant entry in the public API, so it's implementation-specific. E.g. for
автоматически удалять ввод/вывод
evidenceиз истории сразу после выполнения. Это можно сделать с помощью префиксной магии.- IPython:
HistoryManager
doesn't have any facilities to remove entries (neither from DB nor from variables). Alas, hacking the DB by hand/replacing stockHistoryManager
is necessary. Also note that the class has an optional cache ofHistoryManager.db_cache_size
(disabled by default). - readline:
remove_history_item(index)
находится в API. Вам нужно знать количество строк во входных данных.
- IPython:
В качестве альтернативы, если это требуется только для ввода паролей, рассмотрите другие способы, которые не отображают пароль на экране (то есть не делают его частью истории консоли):
getpass.getpass()
- хранить его в другом месте (например, файл конфигурации, доступный только для чтения вами)
%toggle
,your_command
,%toggle
; 2) это означает заменить эти функции обертками вокруг них; пример выходит за рамки ответа, это должно быть понятно любому, у кого есть приличный опыт.
- person ivan_pozdeev; 22.11.2016
Я думаю, что наконец-то понял это. Этот метод на самом деле не «предотвращает» ipython для записи истории, а фактически удаляет запись истории. Но я все же думаю, что это хороший способ достичь этой цели.
История ipython хранится в файле базы данных sqlite в $(ipython locate)/profile_default/history.sqlite
.
Таблица базы данных History состоит из четырех столбцов: session, line, source и source_raw. . Столбец session представляет session_id
текущего сеанса, его можно получить с помощью метода в ipython: get_ipython().history_manager.hisdb.get_last_session_id()
в ipython
. Столбец line — это просто номер строки.
Итак, что я собираюсь сделать, так это удалить эту запись в базе данных в среде ipython
:
1) Объект базы данных истории можно получить с помощью 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» означает удалить запись строки history в базе данных и перезаписать массив In и 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
Я сам искал решение, а потом понял, что могу просто input
раскрыть секрет. Например, я использовал приведенное ниже для инициализации API github при использовании pygithub:
In [1]: gh = github.Github(base_url="https://api.github.com", login_or_token=input("token: "))
token: abcd
In [2]: %hist
gh = github.Github(base_url="https://api.github.com", login_or_token=input("token: "))
%hist