[英]Python tab-completion not working in interactive console (Ubuntu 20.04)
[英]How can I get tab-completion to work in gdb's Python-interactive (pi) shell?
通常,在 Python shell 中,我可以按两次 Tab 来获取提示列表。
另一方面,在 gdb 的 Python shell ( pi
或python-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
库。 有关更多详细信息,请参阅问题中的失败尝试。
重置标准输出和标准错误。
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 可以在分页时执行“按回车继续”限制)
启动一个kernel,单独启动一个控制台。
import IPython IPython.embed_kernel()
阅读控制台 output 以了解如何连接,以及如何从远程控制台退出终端。
使用我的其他答案,也可以以编程方式远程退出终端。
启动一个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()
使用background_zmq_ipython
启动 kernel(访问内部属性,可能随时中断)。
主要区别在于sys.stdin
、 sys.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.