PDB中的自动完成和Tab键

27

我一直在试图让 TAB 键在 (pdb) 提示符下执行除插入制表符以外的其他操作。

我的想法是触发自动完成,例如在 这里这里,但是 TAB 键除了向 pdb 添加制表符之外什么都不做。

因此:

(pdb)var + 按下TAB键

我希望得到:

(pdb)variable

而不是:

(pdb)var[          ]

似乎是我的Python安装出了问题,在另一台电脑上,这两个链接都能够完美地工作。 - Rodrigo Lopez
4个回答

29

iPython是用于解决这个问题的第三方解决方案。有时您只能依赖原始的Python。我找到了2种解决方案。

对于每个终端的解决方案-使用“rlcompleter”模块:

$ python3

Python 3.4.3 (default, Sep 14 2016, 12:36:27) 
[GCC 4.8.4] on linux
Type "help", "copyright", "credits" or "license" for more information.

>>> import pdb
>>> pdb.set_trace()
--Return--
> <stdin>(1)<module>()->None

# press tab - but nothing
(Pdb) str.
*** SyntaxError: invalid syntax
(Pdb) --KeyboardInterrupt--
(Pdb) c
>>> import rlcompleter
>>> pdb.Pdb.complete=rlcompleter.Completer(locals()).complete
>>> pdb.set_trace()
--Return--
> <stdin>(1)<module>()->None
(Pdb) str.
str.__add__(            str.__getattribute__(   str.__name__            str.__text_signature__  str.isdigit(            str.rfind(
str.__base__(           str.__getitem__(        str.__ne__(             str.__weakrefoffset__   str.isidentifier(       str.rindex(
str.__bases__           str.__getnewargs__(     str.__new__(            str.capitalize(         str.islower(            str.rjust(
str.__basicsize__       str.__gt__(             str.__prepare__(        str.casefold(           str.isnumeric(          str.rpartition(
str.__call__(           str.__hash__(           str.__qualname__        str.center(             str.isprintable(        str.rsplit(
str.__class__(          str.__init__(           str.__reduce__(         str.count(              str.isspace(            str.rstrip(
str.__contains__(       str.__instancecheck__(  str.__reduce_ex__(      str.encode(             str.istitle(            str.split(
str.__delattr__(        str.__itemsize__        str.__repr__(           str.endswith(           str.isupper(            str.splitlines(
str.__dict__            str.__iter__(           str.__rmod__(           str.expandtabs(         str.join(               str.startswith(
str.__dictoffset__      str.__le__(             str.__rmul__(           str.find(               str.ljust(              str.strip(
str.__dir__(            str.__len__(            str.__setattr__(        str.format(             str.lower(              str.swapcase(
str.__doc__             str.__lt__(             str.__sizeof__(         str.format_map(         str.lstrip(             str.title(
str.__eq__(             str.__mod__(            str.__str__(            str.index(              str.maketrans(          str.translate(
str.__flags__           str.__module__          str.__subclasscheck__(  str.isalnum(            str.mro(                str.upper(
str.__format__(         str.__mro__             str.__subclasses__(     str.isalpha(            str.partition(          str.zfill(
str.__ge__(             str.__mul__(            str.__subclasshook__(   str.isdecimal(          str.replace(            
(Pdb) c
>>>

系统范围解决方案 - 使用文件 ~/.pdbrc

$ cat ~/.pdbrc
import rlcompleter
pdb.Pdb.complete=rlcompleter.Completer(locals()).complete
$ python3
Python 3.4.3 (default, Sep 14 2016, 12:36:27) 
[GCC 4.8.4] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import pdb
>>> pdb.set_trace()
--Return--
> <stdin>(1)<module>()->None
(Pdb) str.
str.__add__(            str.__getattribute__(   str.__name__            str.__text_signature__  str.isdigit(            str.rfind(
str.__base__(           str.__getitem__(        str.__ne__(             str.__weakrefoffset__   str.isidentifier(       str.rindex(
str.__bases__           str.__getnewargs__(     str.__new__(            str.capitalize(         str.islower(            str.rjust(
str.__basicsize__       str.__gt__(             str.__prepare__(        str.casefold(           str.isnumeric(          str.rpartition(
str.__call__(           str.__hash__(           str.__qualname__        str.center(             str.isprintable(        str.rsplit(
str.__class__(          str.__init__(           str.__reduce__(         str.count(              str.isspace(            str.rstrip(
str.__contains__(       str.__instancecheck__(  str.__reduce_ex__(      str.encode(             str.istitle(            str.split(
str.__delattr__(        str.__itemsize__        str.__repr__(           str.endswith(           str.isupper(            str.splitlines(
str.__dict__            str.__iter__(           str.__rmod__(           str.expandtabs(         str.join(               str.startswith(
str.__dictoffset__      str.__le__(             str.__rmul__(           str.find(               str.ljust(              str.strip(
str.__dir__(            str.__len__(            str.__setattr__(        str.format(             str.lower(              str.swapcase(
str.__doc__             str.__lt__(             str.__sizeof__(         str.format_map(         str.lstrip(             str.title(
str.__eq__(             str.__mod__(            str.__str__(            str.index(              str.maketrans(          str.translate(
str.__flags__           str.__module__          str.__subclasscheck__(  str.isalnum(            str.mro(                str.upper(
str.__format__(         str.__mro__             str.__subclasses__(     str.isalpha(            str.partition(          str.zfill(
str.__ge__(             str.__mul__(            str.__subclasshook__(   str.isdecimal(          str.replace(            
(Pdb) c
>>> 

注意:

  1. 仅在Python 3.4上进行过测试

  2. 操作系统 - Linux Mint

  3. 基于https://reminiscential.wordpress.com/2009/06/12/python-enable-auto-complete-in-a-pdb-session/


2
要使用 python -m pdb script.py 调用 pdb,您还应该在 .pdbrc 中导入 pdb - jdhao
我正在使用 .pdbrc 文件。我的 Python3.7 安装缺少 gnureadline。所以如果这种方法不起作用,请尝试 pip install gnureadline - tharndt
Jupyter笔记本怎么样?考虑到tabKeyPressed实际上会将焦点移动到下一个单元格,这有意义吗?(例如,如果我使用%%debug)-谢谢! - jjrr
FYI,这个答案是针对GNU readline的。关于NetBSD,请参见我的回答 - Constantin Hong

15

ipdb 来解救你。

ipdb 导出函数以访问 IPython 调试器,具有制表符完成、语法高亮、更好的回溯、更好的内省功能,与 pdb 模块相同的接口。


2
我确实尝试了一段时间,它确实做到了它应该做的事情。只是我不太喜欢它。 - Rodrigo Lopez
@RodrigoLopez:你用/做什么替代? - danuker
PDB自动完成最终起作用了(我的安装可能有些问题)。PDB完成了任务(说实话,今天我可能会使用VSC)。 - Rodrigo Lopez
大约一半的时间,ipdb 对我的使用情况不起作用(它会崩溃并显示无意义的错误,这些错误没有任何谷歌搜索结果,而当我尝试调试代码时,我没有时间调试我的调试器)。 - vlsd
1
@vlsd,我已经使用ipdb多年了,从未出现过崩溃。 - shx2
@shx2,这很棒,但它并没有改变我的经验;在功能方面,ipdb非常出色,但我最初来到这个线程的主要原因是因为在标准调试器中打开一个功能比尝试调试第三方调试器更容易。 - vlsd

11

官方文件指出:

自版本3.3起:通过readline模块进行制表符补全可用于命令和命令参数,例如当前全局和本地名称作为p命令的参数。

https://docs.python.org/3/library/pdb.html

因此,您只需使用 p 命令即可:

(Pdb) p var[TAB] # complete global and local names
var1 var2
(Pdb) [TAB] # complete commands
EOF        b          cl         cont       disable    exit       interact   list       next       quit       retval     source     unalias    up         
a          break      clear      continue   display    h          j          ll         p          r          run        step       undisplay  w          
alias      bt         commands   d          down       help       jump       longlist   pp         restart    rv         tbreak     unt        whatis     
args       c          condition  debug      enable     ignore     l          n          q          return     s          u          until      where 

1
这很好!可以验证在Python 3.7.1中工作。 - jmunsch
感谢您的澄清:当您在Pdb repl中输入变量名称时,它会打印其内容,但不会让您自动完成。如果您使用Pdbp命令,基本上用于相同的用例,您将获得自动完成。 - YuvalHelman
我认为这个解决方案应该得到赞同,因为它不需要用户安装第三方工具。用户只需要在变量前加上"p [空格]",它就会自动完成变量名,并显示对象的函数和变量。(例如:在导入sys之后,p sys.[tab]将显示sys对象的所有函数和变量) - EuWern

1
如果您在 macOS 上使用 NetBSD libedit(默认),或者您的 Python 没有编译使用 GNU readline lib 而是 NetBSD libedit,请在 `~/.editrc` 中插入 `python:bind ^I rl_complete`。 在这种情况下,`^I` 有两个字符(`^` 和 `I`)。
此外,您还需要删除尝试过的 GNU readline 解决方案,例如 `~/.pdbrc`(或 `./.pdbrc`)中的某些部分或 答案 中的 `rlcompleter`。

这对我来说没有起作用。但其他答案也没有起作用,所以我觉得很可能在Mac上使用readline和tab时存在问题。 - undefined
@Matthias 试试在 ~/.editrc 中加入这个 python:bind "\011" rl_complete。我已经更新了我的 Python PR(https://github.com/python/cpython/pull/107748#issuecomment-1668593509)。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接