简体   繁体   English

持久性Python命令行历史记录

[英]Persistent Python Command-Line History

I'd like to be able to "up-arrow" to commands that I input in a previous Python interpreter. 我希望能够“向上箭头”到我在之前的Python解释器中输入的命令。 I have found the readline module which offers functions like: read_history_file , write_history_file , and set_startup_hook . 我已经找到了readline模块,该模块提供了类似功能: read_history_filewrite_history_fileset_startup_hook I'm not quite savvy enough to put this into practice though, so could someone please help? 虽然我还不够精明,但有人可以帮忙吗? My thoughts on the solution are: 我对解决方案的看法是:

(1) Modify .login PYTHONSTARTUP to run a python script. (1)修改.login PYTHONSTARTUP以运行python脚本。 (2) In that python script file do something like: (2)在那个python脚本文件中执行以下操作:

def command_history_hook():
    import readline
    readline.read_history_file('.python_history')
command_history_hook()

(3) Whenever the interpreter exits, write the history to the file. (3)每当解释器退出时,将历史记录写入文件。 I guess the best way to do this is to define a function in your startup script and exit using that function: 我想最好的方法是在你的启动脚本中定义一个函数并使用该函数退出:

def ex():
    import readline
    readline.write_history_file('.python_history')
    exit()

It's very annoying to have to exit using parentheses, though: ex() . 但是,必须使用括号退出是非常烦人的: ex() Is there some python sugar that would allow ex (without the parens) to run the ex function? 是否有一些python糖允许ex (没有parens)运行ex函数?

Is there a better way to cause the history file to write each time? 是否有更好的方法可以使历史文件每次都写入? Thanks in advance for all solutions/suggestions. 提前感谢所有解决方案/建议。

Also, there are two architectural choices as I can see. 此外,我可以看到有两种架构选择。 One choice is to have a unified command history. 一种选择是拥有统一的命令历史记录。 The benefit is simplicity (the alternative that follows litters your home directory with a lot of files.) The disadvantage is that interpreters you run in separate terminals will be populated with each other's command histories, and they will overwrite one another's histories. 好处是简单性(后面的替代方案使用大量文件来填充您的主目录。)缺点是您在不同终端中运行的解释器将填充彼此的命令历史记录,并且它们将覆盖彼此的历史记录。 (this is okay for me since I'm usually interested in closing an interpreter and reopening one immediately to reload modules, and in that case that interpreter's commands will have been written to the file.) One possible solution to maintain separate history files per terminal is to write an environment variable for each new terminal you create: (这对我来说没问题,因为我通常有兴趣关闭一个解释器并立即重新打开一个解码器来重新加载模块,在这种情况下,解释器的命令将被写入文件。)一种可能的解决方案来维护每个终端的单独历史文件是为您创建的每个新终端编写环境变量:

def random_key()
    ''.join([choice(string.uppercase + string.digits) for i in range(16)])

def command_history_hook():
    import readline
    key = get_env_variable('command_history_key')
    if key:
        readline.read_history_file('.python_history_{0}'.format(key))
    else:
        set_env_variable('command_history_key', random_key())

def ex():
    import readline
    key = get_env_variable('command_history_key')
    if not key:
        set_env_variable('command_history_key', random_key())
    readline.write_history_file('.python_history_{0}'.format(key))
    exit()

By decreasing the random key length from 16 to say 1 you could decrease the number of files littering your directories to 36 at the expense of possible (2.8% chance) of overlap. 通过将随机密钥长度从16减少到1,您可以将丢失目录的文件数减少到36,但代价是可能的重叠(2.8%)。

I think the suggestions in the Python documentation pretty much cover what you want. 我认为Python文档中的建议几乎涵盖了你想要的东西。 Look at the example pystartup file toward the end of section 13.3: 查看第13.3节末尾的示例pystartup文件:

or see this page: 或看到这个页面:

But, for an out of the box interactive shell that provides all this and more, take a look at using IPython: 但是,对于提供所有这些以及更多内容的开箱即用的交互式shell,请看一下使用IPython:

Try using IPython as a python shell. 尝试使用IPython作为python shell。 It already has everything you ask for. 它已经拥有了你要求的一切。 They have packages for most popular distros, so install should be very easy. 他们有最流行的发行包的包,所以安装应该很容易。

Persistent history has been supported out of the box since Python 3.4. 自Python 3.4以来,已经支持持久历史。 See this bug report . 请参阅此错误报告

使用PIP安装pyreadline包:

pip install pyreadline

If all you want is to use interactive history substitution without all the file stuff, all you need to do is import readline: 如果你想要的只是在没有所有文件的情况下使用交互式历史替换,你需要做的就是导入readline:

import readline

And then you can use the up/down keys to navigate past commands. 然后,您可以使用向上/向下键来导航过去的命令。 Same for 2 or 3. 2或3相同。

This wasn't clear to me from the docs, but maybe I missed it. 我从文档中不清楚这一点,但也许我错过了它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM