关于 Jupyter Console 没有自动提示 (补全) 的修复

news/2025/2/22 22:22:19

现象描述

在命令行中通过 jupyter console 进入控制台, 发现输入命令时, 不会自动弹出提示. 比如:

a = 1  # 我在第一行输入了 `a = 1`
a  # 当输入第一个字母 "a" 时, 按理来说应该弹出补全提示 " = 1", 但是没有

解决方法

该操作需要修改 jupyter-console 的源文件:

  1. 源文件位于: {site-packages}/jupyter_console/ptshell.py

  2. 在第 47 行插入以下内容:

    from prompt_toolkit.auto_suggest import AutoSuggestFromHistory  # <--- HERE
    

    示意图:

    ...
    from prompt_toolkit import __version__ as ptk_version
    PTK3 = ptk_version.startswith('3.')
    
    if not PTK3:
        # use_ayncio_event_loop obsolete in PKT3
        from prompt_toolkit.eventloop.defaults import use_asyncio_event_loop
    
    from prompt_toolkit.auto_suggest import AutoSuggestFromHistory  # <--- HERE
    from prompt_toolkit.completion import Completer, Completion
    from prompt_toolkit.document import Document
    from prompt_toolkit.enums import DEFAULT_BUFFER, EditingMode
    ...
    
  3. 在第 559 行插入以下内容:

    auto_suggest=AutoSuggestFromHistory(),  # <--------------------------- HERE
    

    示意图:

    ...
    # Tell prompt_toolkit to use the asyncio event loop.
    # Obsolete in prompt_toolkit.v3
    if not PTK3:
        use_asyncio_event_loop()
    
    self.pt_cli = PromptSession(
        auto_suggest=AutoSuggestFromHistory(),  # <----------------------- HERE
        message=(lambda: PygmentsTokens(self.get_prompt_tokens())),
        multiline=True,
        complete_style=self.pt_complete_style,
        editing_mode=editing_mode,
        lexer=PygmentsLexer(get_pygments_lexer(lexer)),
        prompt_continuation=(
            lambda width, lineno, is_soft_wrap: PygmentsTokens(
                self.get_continuation_tokens(width)
            )
        ),
        ...
    )
    ...
    

即可解决.

测试一下效果

该测试场景模拟了 A 窗口启动了 ipython 内核服务, B 窗口使用 jupyter console 连接该服务, 并获得完美的自动补全功能.

# test/ipython_service.py
from IPython import embed_kernel

def hello():
    print('hello world')

embed_kernel(user_ns={
    'a'    : 'alpha',
    'b'    : 'beta',
    'hello': hello,
})

打开一个命令行, 作为 A 窗口, 输入以下命令:

python test/ipython_service.py
# 控制台出现打印信息: 
#   to connect another client to this kernel, use:
#       --existing kernel-12345.json

再新开一个命令行, 作为 B 窗口, 输入以下命令:

jupyter console --existing 12345

尝试输入以下命令, 可以观察到自动补全的效果:

a, b
a + b  # 当输入 "a" 时, 会提示 ", b"
a, b, hello()  # 当输入 "a" 时, 会提示 " + b"; 继续输入 "a,", 会转为提示 " b"
...

exit()
#   exit(keep_kernel=False)  # 断开 B 且停止 A. (默认)
#   exit(keep_kernel=True)  # 断开 B 但不停止 A.

附录: 研究过程

prompt-toolkit 是一个 python 库, 用来给命令行 REPL 提供上下文感知, 自动补全, 历史记录等功能. 它是 ipythonjupyter 的重要依赖之一.

jupyter consoleipython 都会启动命令行界面, 但二者在体验上存在一些不同之处, 其中最显著的就是前者没有自动补全, 而后者有, 因此使用体验受到影响. 好在本文就是为了解决这个问题的.

观察 jupyter console -h 的参数, 有一个 --no-simple-prompt, 是用来启用 prompt-toolkit 的功能的.

按理来说 jupyter console 提供这个参数, 就应该能够使用自动补全功能, 但本人测试最新版 (截至 2023-07-01) 并没有作用, 个人怀疑是 jupyter 的一个 bug.

此外, 根据官方文档描述, 启动 jupyter console 的命令行界面后, 使用下面的命令也能激活自动补全功能:

通过阅读 jupyter_console 的源代码, 发现 jupyter_console/ptshell.py 文件确实少了 prompt_toolkit.auto_suggest.AutoSuggestFromHistory, 所以问题就好解决了, 把它作为参数传到 ZMQTerminalInteractiveShell.pt_cli 的实例化构造中即可.


http://www.niftyadmin.cn/n/1461436.html

相关文章

redis 如何查看版本号

linux环境下查看redis的版本&#xff1a; 查看redis的版本有两种方式&#xff1a; 1. redis-server --version 和 redis-server -v 得到的结果是&#xff1a;Redis server v3.2.12 sha00000000:0 mallocjemalloc-3.6.0 bits64 1. redis-cli --version 和 redis-cli -v 得到…

B bit 比特 字节 单位换算

1比特(bit)0.125字节(b) 1B1byte ,就是1个字节。 Byte、KB、B、MB、GB之间的关系是&#xff1a; Bit——比特 B(byte) ——字节 (BYTE) KB——千字节 MB——兆字节 GB——吉字节 TB——太字节 1B8 Bit 1KB&#xff1d;1024B 1MB&#xff1d;1024KB 1GB&#xff1d;1…

mysql+游标+分批提交_mysql游标批量操作

BEGINDECLARE _uuid VARCHAR(60);DECLARE _insertNum INT DEFAULT 0;DECLARE done int DEFAULT 0;#定义游标DECLARE rs_cursor CURSOR FORSELECT uuid,(10-IFNULL(rateNum,0)) as insertNum from product pLEFT JOIN(SELECT product_uuid,count(product_uuid) AS rateNum FROM …

python 单例模式 redis_redis_single.py

# -*- coding: utf-8 -*-"""使用文档&#xff1a;本文件是Redis连接的全局单例模式&#xff0c;>>> XzxRedis().r>>> Redis>>XzxRedis().r返回一个 redis 数据库的链接池对象author: zpj"""import redis########Redis 数…

python自动化广告收益_薅羊毛? 月入10万? | 这是自动化测试老司机的特长--Python自动化带你薅视频红包,一个都不放过!...

一、目标场景如今短视频横行的时代&#xff0c;以某短视频为首的&#xff0c;背后依靠着强大的资金后盾&#xff0c;疯狂地对平台用户进行红包轰炸。​与传统的红包不一样&#xff0c;视频红包包含位置的不确定性、大小不确定性、元素 ID 的不确定性等......这些不确定性都会导…

CCNP知识点总结——交换部分

1、交换机 交换机工作在OSI的数据链路层&#xff0c; 可分为2层和多层交换机。按照网络位置可划分为接入层、分布层、核心层交换机。其重要参数有&#xff1a;背板带宽、接口速率、转发速率。 2、VLAN技术 VLAN是一个单独的广播域。交换机的一个端口只能承载单个VLAN的流量&…

mysql主主复制报错_mysql主主复制汇总整理

#注意在mysql配置文件中填写一下信息的位置&#xff0c;必须为此位置&#xff0c;即[mysqld]标签下面[mysqld]#任意自然数n&#xff0c;只要保证两台MySQL主机不重复就可以了server-id1#起始值。一般填第n台主MySQL。此时为第一台主MySQLauto_increment_offset1#步进值auto_imc…

python存储数据的结构_如何使用数据存储结构来减少数据存储的外观?

在使用appengine mapreduce lib时&#xff0c;如何按StructuredProperty进行筛选&#xff1f;在我试过了&#xff1a;class Tag(ndb.Model):# ...tag ndb.StringProperty()value ndb.FloatProperty(indexedFalse)class User(ndb.Model):# ...tags ndb.StructuredProperty(Ta…