2017-05-29 61 views
0

我已经创建了一个基于PyQt4的基于GUI的大型python程序。我希望该软件包可以在IPython笔记本(Windows上的Python 2.7旧安装),Jupyter笔记本(最近安装了Anaconda的Python 3.5)以及在命令行上传递的Python程序中运行。我在Jupyter笔记本上运行代码时遇到问题(请直接在底部查看)。为什么PyQt4在Jupyter和IPython笔记本之间有不同的表现?

我模块mymodule.py看起来是这样的(极度简化,许多其他Python文件前戏约10000行):

from PyQt4 import QtCore, QtGui 

class MyModule(object): 
    def __init__(self): 
     self.window = QtGui.QMainWindow() 
     self.window.show() 

命令行的典型用法是

python myscript.py 

与以下文件myscript.py

from PyQt4 import QtCore, QtGui 
import mymodule 

m = mymodule.MyModule() 

APP = QtGui.QApplication.instance() 
APP.exec_() 

这工作正常。我知道APP.exec_()需要启动某种通过Gui交互事件工作的EventLoop。

在IPython的笔记本,用户通常不会

import mymodule 
m = mymodule.MyModule() # opens the gui 
# this still leaves the console active to allow things like this: 
m.change_color("red") 

我没有问题,我在那里understant是IPython的莫名其妙照顾的事件循环的幕后运行此。

现在,在Jupyter笔记本中运行相同的命令,将打开一个窗口,但会在允许任何用户交互之前冻结。所以我相信Jupyter笔记本没有正确处理这些事件,因为我没有告诉它这么做。我找到的一种方法是在运行我的代码之前执行命令%pylab。然而,我经常遇到这方面的相关问题,例如在开始我的程序之前直接运行%pylab%matplotlib inline,这会导致我再次加载我的代码后再次冻结(好奇地,颠倒了两个神奇命令的顺序再次运行) 。另外,我不想强​​迫我的程序用户在每个新笔记本中执行%pylab(如果可以避免的话)(也因为我相信这需要matlab安装,这不是我的程序的要求)。

我必须在mymodule.py中添加什么代码才能使事物与Jupyter笔记本中描述的用户代码兼容?任何人都可以更清楚地解释IPython笔记本和Jupyter笔记本如何以不同方式管理QEventLoop/QApplication(或此处的任何重要概念),以及这些魔法命令如何处理这个问题?因为这个原因,我害怕我的程序中存在隐藏的错误,并且希望尽可能使其不会让用户感到沮丧。

回答

0

这是一个工作解决方案,它允许运行代码而不区分不同的IPython/Jupyter版本和“原始”Python。我__init__.py文件包含在开始本节:

# enable IPython QtGui support if needed 
try: 
    from IPython import get_ipython 
    get_ipython().magic('gui qt') 
except BaseException as e: 
    # issued if code runs in bare Python 
    print('Could not enable IPython gui support: %s.' % e) 

# get QApplication instance 
from PyQt4 import QtCore, QtGui 
APP = QtGui.QApplication.instance() 
if APP is None: 
    print('Creating new QApplication instance "mymodule"') 
    APP = QtGui.QApplication(['mymodule']) 

对原材料的Python运行脚本,然后只需要这样:

import mymodule # imports the above code 
from PyQt4 import QtCore, QtGui 
if __name__ == '__main__': 
    QtGui.QApplication.instance().exec_() 

我没有发现任何使用情况下这是行不通的。

相关问题