如何避免将命令存储在 ipython 历史记录中?

how can I avoid storing a command in ipython history?

在 bash 中,我可以通过在命令前面放置 space 来防止将命令保存到 bash 历史记录中。我无法在 ipython 中使用此方法。我将如何做 ipython 中的等价物?

我想我终于弄明白了。这个方法不是真正'prevent'ipython记录历史而是删除历史记录。但我认为这仍然是实现这一目标的好方法。

ipython 历史存储在 $(ipython locate)/profile_default/history.sqlitesqlite 数据库 文件中。

数据库table 历史有四列:session, line , 来源source_rawsession列代表当前session的session_id,可以通过ipython中的方法获取:get_ipython().history_manager.hisdb.get_last_session_id() in ipython . line 列只是行号。

所以我要做的是删除数据库中ipython环境中的这条记录:

1) 历史数据库对象可以在ipython

中使用get_ipython().history_manager.db获取
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 Array List 也有点像历史,但它存储在内存中,所以它可以像变量一样被清除或重写。

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

到'prevent a command from being saved to ipython history',表示删除数据库中该行的历史记录,并重写In ipython 环境中的 Out 数组。我们可以将这四行合并为一条,一次性完成所有工作。 这里有一个例子如果我们要删除第 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

过时说明:这是为 IPython 4.0.1 编写的。 As of v5, IPython no longer uses readline.


没有库存方式,可以添加或变通。

IPython有两种历史:

  • readline 历史。它可用于特殊的 keys/key 组合(up/down、Ctrl-R 等)。仅存储在控制台上输入(使用 <Enter>)的行(或者,在 pyreadline 中,也从剪贴板粘贴)。 IPython 依赖于 Python readline API 的本地实现,它没有 "do not add" 函数,通常会将每一行添加到历史记录中。
    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.interactstore_history=True.

  • 调用

有两种方法可以解决任一层的问题:

  • 首先阻止添加输入。这不能用命令前缀的魔法来完成,只能用 运行 作为单独的命令并切换标志。那是因为,如您所见,当前输入在魔术命令获得控制权时已经存储。

    • readline:public API 中没有相关条目,因此它是特定于实现的。例如。对于 pyreadline,添加是用 pyreadline.modes.basemode.BaseMode.add_history() 完成的。模式对象可以作为 get_ipython().readline.rl.mode.
    • 访问
    • 装饰 run_celladd_history 使用包装器检查相应对象中的标志和 custom magic command sets/toggles 它们应该可以解决问题。
  • 执行后立即从历史记录中自动删除 证据 input/output。这可以通过前缀魔法来完成。

    • IPython: HistoryManager 没有任何删除条目的工具(无论是从数据库还是从变量)。 las,通过 hand/replacing stock HistoryManager 破解数据库是必要的。另请注意,class 有一个可选的 HistoryManager.db_cache_size 缓存(默认情况下禁用)。
    • readline:remove_history_item(index) 在 API 中。您需要知道输入中的行数。

或者,如果您只需要它来输入密码,请考虑其他不会在屏幕上回显密码的方法(因此不会使其成为控制台历史记录的一部分):

我自己正在寻找解决方案,然后意识到我可以 input 这个秘密。例如,我在使用 pygithub:

时使用下面的代码初始化 github API
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