簡體   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