6

我找到了一种交互式处理curses 的方法,同时还能享受IPython 的大部分好处。它可以工作,但有一些限制,但没有我想要的那么好。

当然,最初的问题是我希望能够使用我的交互式 Python 会话,同时让它控制终端屏幕,使用 curses (ncurses) 模块(或urwid,例如)。一种解决方案是编写一个简单的 TCP 服务器,它带有一个简单的事件循环,该循环评估它从套接字读取的每个字符串,并发送回表示并返回结果的序列化字符串。如此处所述:SO:有没有一种方法可以交互式地对 Python curses Application 进行编程)。

这是一个更简单的技巧(假设您安装了 IPython)。

    #!/usr/bin/python 
    #!/usr/bin/env python 
    from IPython import embed_kernel
    import curses

    def interact_with_curses(screen):
        '''set global stdscr variable and run embedded IPython kernel
           suitable to be called by curses.wrapper()
        '''
        global stdscr
        stdscr = screen
        embed_kernel()

    if __name__ == '__main__':
        curses.wrapper(interact_with_curses)

(稍微调整一下以使 SO 的语法突出显示快乐)。

运行这将导致输出大致如下:

 [IPKernelApp] To connect another client to this kernel, use:
            [IPKernelApp] --existing kernel-2869.json

并切换到另一个窗口或屏幕会话,您可以运行:

ipython console --existing kernel-2869.json

连接到该过程并使用它。

这已经足够好了。然后,您可以调用诸如stdscr.refresh(). 使用你的 curses/window 和 pad 对象,调用dir()它们来探索它们的功能,并且通常使用代码就像你在一个普通的 IPython 会话中一样,它恰好正在更新另一个终端的屏幕并从中读取(通过诅咒输入函数)。

这种方法的问题和问题:

  • 要退出似乎我必须从 IPython 控制台运行 quit() ,这不会以正常方式退出解释器。它似乎不允许curses.wrapper()重置终端,并且各种尝试调用.endwin(), .resetty()(当然在执行 a.savetty()之后),.reset_shell_mode()(and .reset_prog_mode()) 等等都失败了。我已经尝试在调用之后在 main 中调用它们,curses.wrapper()并且我已经尝试将它们注册为atexit
    • 我如何干净地退出这样的会话?
  • [Tab] 完成不起作用
    • 如何让 IPython 的 [Tab] 通过 IPython 控制台会话完全工作到这些嵌入式内核之一?
  • 调用 IPythonembed_kernel()函数会将套接字信息打印到 curses 屏幕,此时该屏幕已经被初始化curses.wrapper()。这很难看;另外,如果想做更有趣的工作,在curses中和调用embed_kernel()函数之前,我看不到该函数打印到stdout或stderr的文本。
    • 如何embed_kernel()保持沉默并强制它通过其他机制注册连接详细信息?我可以给它我自己的套接字名称/使用路径吗?

我相信我会想到其他问题,但我希望其他人会发现这个技巧很有用,并且会发现我想涉足 Python 诅咒编码时可以使用的其他技巧。

4

2 回答 2

8

事实证明,我们现在可以以一种相当自然的方式使用 IPython 以交互方式处理 curses。

从一个终端只需键入:

ipython kernel

这将打印如下一行:

[IPKernelApp] To connect another client to this kernel, use:
[IPKernelApp] --existing kernel-14321.json

从另一个终端/窗口类型:

ipython console --existing kernel-14321.json

...您将进入一个看似完全正常的 IPython 会话。唯一的区别是您实际上是在另一个窗口中访问“远程”IPython 内核会话。从那里您将能够使用 curses 函数、查看另一个窗口中的更改、对其输入输入、使用 [Tab]-completion 等等。

请注意,[Ctrl]-[D] 将提供退出 IPython控制台(客户端),同时quit()将关闭 IPython内核(远程窗口 --- 服务器)。

但是,总的来说,这个模型比我去年在我的问题中描述的更干净、更容易。我不知道是不是新版本的 IPython (0.13.1) 还是简单的无知让我之前的尝试有些笨拙。

于 2013-03-17T04:56:35.730 回答
2

我找到了选项卡完成的答案,您可以使用获取 IPython shell 对象get_ipython(),然后调用init_completer()它:

get_ipython().init_completer()

应该可以获取内核并关闭它,退出终端应用程序。但是在文档中爬行到目前为止还没有发现如何。

于 2012-08-31T09:41:45.347 回答