【问题标题】:how can I avoid storing a command in ipython history?如何避免在 ipython 历史记录中存储命令?
【发布时间】:2016-05-07 17:20:45
【问题描述】:

在 bash 中,我可以通过在命令前面放置一个空格来防止将命令保存到 bash 历史记录中。我不能在 ipython 中使用这种方法。我将如何在 ipython 中进行等效操作?

【问题讨论】:

标签: python ipython history


【解决方案1】:

我自己在寻找解决方案,然后意识到我可以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

【讨论】:

    【解决方案2】:

    过时说明:这是为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>'ed 行用于多行)和输出。保存在HistoryManager.store_inputs()(用于输入)和HistoryManager.store_output()(用于输出)中实现,从InteractiveShell.run_cell 调用并由其store_history 参数控制。后者依次从TerminalInteractiveShell.interactstore_history=True 调用。

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

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

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

      • IPython:HistoryManager 没有任何工具可以删除条目(无论是从数据库中还是从变量中)。唉,手动破解数据库/更换库存HistoryManager 是必要的。另请注意,该类有一个可选的缓存 HistoryManager.db_cache_size(默认禁用)。
      • readline:remove_history_item(index) 在 API 中。您需要知道输入中的行数。

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

    • getpass.getpass()
    • 将其存储在其他地方(就像只有您可以读取的配置文件)

    【讨论】:

    • 1. “首先防止添加输入。这不能通过在命令前添加魔法来完成,只能使用作为单独命令运行并切换标志的魔法”单独的命令切换标志以防止添加输入? 2. 用包装器检查相应对象中的标志和设置/切换它们的自定义魔术命令来装饰 run_cell 和 add_history 应该可以解决问题。你能添加一个例子吗?
    • @ShreevatsaR 0) 见过时说明; 1)%toggle,your_command,%toggle; 2)这意味着用它们周围的包装器替换这些函数;一个例子超出了答案的范围,任何具有相当专业知识的人都应该清楚。
    【解决方案3】:

    我想我终于弄明白了。这种方法并没有真正“阻止” ipython 记录历史记录,而是实际上删除历史记录。但我认为这仍然是实现这一目标的好方法。

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

    数据库表History有四列:sessionlinesourcesource_raw。 session 列表示当前会话的session_id,可以通过ipython 中的方法得到:get_ipython().history_manager.hisdb.get_last_session_id() in ipythonline 列就是行号。

    所以我要做的是在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]=''
    

    “防止命令被保存到 ipython 历史”,是指删除数据库中该行的 history 记录,并重写 InOut 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

    【讨论】:

    • 这并没有真正“避免在历史记录中存储一行”,而是将其从历史记录中删除。
    • @ivan_pozdeev 我知道。但是我通读了 ipython 文档,找不到真正“防止命令保存到历史记录”的方法,所以我发现如果我删除该行会做同样的工作。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-08-07
    • 1970-01-01
    • 2011-03-11
    • 1970-01-01
    • 1970-01-01
    • 2017-06-19
    • 1970-01-01
    相关资源
    最近更新 更多