当前位置: 首页 > 面试题库 >

将IPython Qt控制台嵌入PyQt应用程序

汤昊
2023-03-14
问题内容

我想将IPython
qt控制台窗口小部件嵌入正在处理的PyQt应用程序中。下面提供的代码(并改编自(http://codingdict.com/questions/162023))针对IPython
v0.12实现了此功能。然而,这在崩溃的IPython V0.13在该行self.heartbeat.start()RuntimeError: threads can only be started once。注释掉此行将调出小部件,但不响应用户输入。

有谁知道如何实现IPython v0.13的等效功能?

"""
Adapted from
https://stackoverflow.com/a/9796491/1332492
"""
import os
import atexit

from IPython.zmq.ipkernel import IPKernelApp
from IPython.lib.kernel import find_connection_file
from IPython.frontend.qt.kernelmanager import QtKernelManager
from IPython.frontend.qt.console.rich_ipython_widget import RichIPythonWidget
from IPython.config.application import catch_config_error
from PyQt4 import QtCore


class IPythonLocalKernelApp(IPKernelApp):
    DEFAULT_INSTANCE_ARGS = ['']

    @catch_config_error
    def initialize(self, argv=None):
        super(IPythonLocalKernelApp, self).initialize(argv)
        self.kernel.eventloop = self.loop_qt4_nonblocking

    def loop_qt4_nonblocking(self, kernel):
        """Non-blocking version of the ipython qt4 kernel loop"""
        kernel.timer = QtCore.QTimer()
        kernel.timer.timeout.connect(kernel.do_one_iteration)
        kernel.timer.start(1000*kernel._poll_interval)

    def start(self, argv=DEFAULT_INSTANCE_ARGS):
        """Starts IPython kernel app
        argv: arguments passed to kernel
        """
        self.initialize(argv)
        self.heartbeat.start()

        if self.poller is not None:
            self.poller.start()

        self.kernel.start()


class IPythonConsoleQtWidget(RichIPythonWidget):
    _connection_file = None

    def __init__(self, *args, **kw):
        RichIPythonWidget.__init__(self, *args, **kw)
        self._existing = True
        self._may_close = False
        self._confirm_exit = False

    def _init_kernel_manager(self):
        km = QtKernelManager(connection_file=self._connection_file, config=self.config)
        km.load_connection_file()
        km.start_channels(hb=self._heartbeat)
        self.kernel_manager = km
        atexit.register(self.kernel_manager.cleanup_connection_file)

    def connect_kernel(self, connection_file, heartbeat=False):
        self._heartbeat = heartbeat
        if os.path.exists(connection_file):
            self._connection_file = connection_file
        else:
            self._connection_file = find_connection_file(connection_file)

        self._init_kernel_manager()


def main(**kwargs):
    kernelapp = IPythonLocalKernelApp.instance()
    kernelapp.start()

    widget = IPythonConsoleQtWidget()
    widget.connect_kernel(connection_file=kernelapp.connection_file)
    widget.show()

    return widget

if __name__ == "__main__":
    from PyQt4.QtGui import QApplication
    app = QApplication([''])
    main()
    app.exec_()

v0.13的回溯

RuntimeError                              Traceback (most recent call last)
/Users/beaumont/terminal.py in <module>()
     80     from PyQt4.QtGui import QApplication
     81     app = QApplication([''])
---> 82     main()
        global main = <function main at 0x106d0c848>
     83     app.exec_()

/Users/beaumont/terminal.py in main(**kwargs={})
     69 def main(**kwargs):
     70     kernelapp = IPythonLocalKernelApp.instance()
---> 71     kernelapp.start()
        kernelapp.start = <bound method IPythonLocalKernelApp.start of     <__main__.IPythonLocalKernelApp object at 0x106d10590>>
     72 
     73     widget = IPythonConsoleQtWidget()

/Users/beaumont/terminal.py in start(self=<__main__.IPythonLocalKernelApp object>, argv=[''])
     33         """
     34         self.initialize(argv)
---> 35         self.heartbeat.start()
        self.heartbeat.start = <bound method Heartbeat.start of <Heartbeat(Thread-1, started daemon 4458577920)>>
     36 
     37         if self.poller is not None:

/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/threading.pyc in start(self=<Heartbeat(Thread-1, started daemon 4458577920)>)
    487             raise RuntimeError("thread.__init__() not called")
    488         if self.__started.is_set():
--> 489             raise RuntimeError("threads can only be started once")
        global RuntimeError = undefined
    490         if __debug__:
    491             self._note("%s.start(): starting thread", self)

RuntimeError: threads can only be started once

问题答案:

好的,这段代码似乎可以解决问题(即,它在Qt小部件中放置了非阻塞的ipython解释器,可以将其嵌入到其他小部件中)。传递来terminal_widget添加到小部件名称空间的关键字

import atexit

from IPython.zmq.ipkernel import IPKernelApp
from IPython.lib.kernel import find_connection_file
from IPython.frontend.qt.kernelmanager import QtKernelManager
from IPython.frontend.qt.console.rich_ipython_widget import RichIPythonWidget
from IPython.utils.traitlets import TraitError
from PyQt4 import QtGui, QtCore

def event_loop(kernel):
    kernel.timer = QtCore.QTimer()
    kernel.timer.timeout.connect(kernel.do_one_iteration)
    kernel.timer.start(1000*kernel._poll_interval)

def default_kernel_app():
    app = IPKernelApp.instance()
    app.initialize(['python', '--pylab=qt'])
    app.kernel.eventloop = event_loop
    return app

def default_manager(kernel):
    connection_file = find_connection_file(kernel.connection_file)
    manager = QtKernelManager(connection_file=connection_file)
    manager.load_connection_file()
    manager.start_channels()
    atexit.register(manager.cleanup_connection_file)
    return manager

def console_widget(manager):
    try: # Ipython v0.13
        widget = RichIPythonWidget(gui_completion='droplist')
    except TraitError:  # IPython v0.12
        widget = RichIPythonWidget(gui_completion=True)
    widget.kernel_manager = manager
    return widget

def terminal_widget(**kwargs):
    kernel_app = default_kernel_app()
    manager = default_manager(kernel_app)
    widget = console_widget(manager)

    #update namespace                                                           
    kernel_app.shell.user_ns.update(kwargs)

    kernel_app.start()
    return widget

app = QtGui.QApplication([])
widget = terminal_widget(testing=123)
widget.show()
app.exec_()


 类似资料:
  • 问题内容: 我一直在尝试从Java应用程序中检索“ unicode用户输入”,以获得一个小的实用程序片段。问题是,它似乎在“开箱即用”的Ubuntu上运行,我猜它在UTF-8上具有操作系统范围的编码,但是从“ cmd”运行时在Windows上不起作用。考虑的代码如下: 在Ubuntu上的输出(不对配置进行任何更改): 在Windows CMD提示符下输出(绝不受JAVA_TOOL_OPTIONS影

  • 我有一个使用Visual Studio 2010/C#编写的控制台应用程序 我通过属性添加了一个图标-

  • 问题内容: 我已经开发了一个Java控制台应用程序,该应用程序在启动时打开控制台窗口并保持在前台,我想在后台启动该应用程序。 现在,我通过以下命令行启动该应用程序: 有没有办法实现这种行为?更改命令行参数就足够了,还是我需要对代码进行一些更改? 问题答案: 答案取决于操作系统。

  • 我目前正在使用Windows控制台制作一个平台游戏。但是,我在发出多个命令时遇到了一个问题。 例如,当我让我的角色朝一个方向运行,然后按“跳跃”时,按住run键的事实被忘记,必须再次按下。 是否有一种输入法可以检查哪些键被按住或按下?或者更确切地说,是检查重复输入的一种方法? 以下是我目前的代码供参考:http://pastebin.com/2y6Rf6rb 我目前使用的输入法是:

  • sh wget progressbar colorama Gooey——把 CLI 程序变成 GUI

  • 问题内容: 我刚刚开始弄乱JLine来解析控制台模式下的字符输入。看来运作良好,但我想知道: JLine中是否有非阻塞方式来查找字符是否可用?(例如,在Windows中。) 我想我总是可以将键盘输入包装在其自己的线程中,该线程随后将键盘字符提供给主线程一个线程安全的队列,但这似乎是不必要的。 编辑 :这是逐字符解析。我不会使用GUI。在控制台模式下,Java中通常的InputStream I /