繁体   English   中英

如何在 gdb 的 Python 交互式 (pi) shell 中获得制表符补全功能?

[英]How can I get tab-completion to work in gdb's Python-interactive (pi) shell?

通常,在 Python shell 中,我可以按两次 Tab 来获取提示列表。

另一方面,在 gdb 的 Python shell ( pipython-interactive命令)中,只有 gdb 样式的完成。

示例 session:

$ gdb -q
(gdb) pi
>>> gdb
<module 'gdb' from '/usr/share/gdb/python/gdb/__init__.py'>
>>> gdb.TabTab

>>> show TabTab
Display all 148 possibilities? (y or n)
ada                              exec-direction                   record
agent                            exec-done-display                remote
annotate                         exec-file-mismatch               remoteaddresssize

Python 自动完成至少应该是这样的。

$ python
Python 3.
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> sys.TabTab
sys.abiflags                              sys.hash_info
sys.addaudithook(                         sys.hexversion
sys.api_version                           sys.implementation

如何在 gdb 中获得相同/相似的东西? 特别是带有制表符完成的 IPython shell 很好。


失败的尝试:

  • 这个解决方案

    import readline import rlcompleter readline.parse_and_bind("tab: complete")

    当在 sys.tab 之后按下Tab时,使 shell output 成为文字选项卡sys. 或类似的。

    至少它确实适用于标识符选项卡完成( a Tab Tab确实列出了一些条目)

    看起来这是因为与 gdb 的一些交互get_completer_delims都会重置为某个值,如果运行上面的代码,那么 gdb之外的选项卡完成也会切换到“Python 模式”。

  • 使用background_zmq_ipython会导致分段错误,因为无法从主线程外部读取某些 gdb API(例如gdb.Value )。

  • 使用IPython.embed()还可以使Tab output 成为文字制表符。

  • The official gdb documentation https://sourceware.org/gdb/current/onlinedocs/gdb/Completion.html doesn't mention anything about Python.

我想出了几种方法。

我想不出任何方法来使用内置的readline库。 有关更多详细信息,请参阅问题中的失败尝试。


  1. 重置标准输出和标准错误。

     import sys sys.stdout=sys.__stdout__ sys.stderr=sys.__stderr__ import IPython IPython.embed(colors="neutral")

    记得在之后重置 stdout 和 stderr 以避免可能出现的问题。

    参考:

    所有标准输入、标准输出和标准错误都是 tty 设备时,IPython 只会使用制表符补全和颜色。 默认情况下 gdb sys.stdout 和 sys.stderr 是 gdb 包装器(这样 gdb 可以在分页时执行“按回车继续”限制)

  2. 启动一个kernel,单独启动一个控制台。

     import IPython IPython.embed_kernel()

    阅读控制台 output 以了解如何连接,以及如何从远程控制台退出终端。

    使用我的其他答案,也可以以编程方式远程退出终端。

  3. 启动一个kernel(复杂方式)

    阅读IPython的源代码,了解如何手动启动一个kernel,并在此过程中获取连接文件路径。

     import threading import subprocess import IPython from ipykernel.kernelapp import IPKernelApp import sys app = IPKernelApp.instance() app.initialize([]) app.kernel.user_module = sys.modules[__name__] app.kernel.user_ns = locals() app.shell.set_completer_frame() def console_thread_run(): subprocess.run(["jupyter-console", "--no-confirm-exit", "--existing", app.abs_connection_file ]) app.kernel.do_shutdown(restart=False) console_thread=threading.Thread(target=console_thread_run) console_thread.start() app.start()
  4. 使用background_zmq_ipython启动 kernel(访问内部属性,可能随时中断)。

    主要区别在于sys.stdinsys.stdout等不受影响。 请参阅background_zmq_ipython文档和ipython - 为 Python 脚本提供远程 shell - 堆栈内存溢出了解更多详细信息。

     import subprocess import logging import threading from background_zmq_ipython import IPythonBackgroundKernelWrapper kernel_wrapper = IPythonBackgroundKernelWrapper( banner="", # default value is "Hello from background-zmq-ipython." user_ns=globals(), logger=logging.Logger("IPython", level=logging.INFO) # no handler # otherwise it will print "To connect another client to this IPython kernel"... ) kernel_wrapper.thread=threading.main_thread() # workaround for assertions subprocess.Popen(["python", "-c", ( "from jupyter_console.app import ZMQTerminalIPythonApp;" "app = ZMQTerminalIPythonApp();" "app.initialize();" "app.shell.own_kernel=True;" "app.start();" ), "--no-confirm-exit", "--existing", kernel_wrapper.connection_filename ]) kernel_wrapper._thread_loop()

    还展示了如何将消息“保持 kernel 活着”更改为“关闭内核”。

暂无
暂无

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

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