Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Calling sip.setapi does not work if app has already imported from PyQt4 #276

Closed
Sharpie opened this issue Feb 20, 2011 · 4 comments
Closed
Milestone

Comments

@Sharpie
Copy link

Sharpie commented Feb 20, 2011

Take the following example for a minimal Qt shell:

#!/usr/bin/env python
import sys

from PyQt4.QtCore import Qt
from PyQt4.QtGui import QMainWindow, QApplication

from IPython.frontend.qt.kernelmanager import QtKernelManager
from IPython.frontend.qt.console.ipython_widget import IPythonWidget


class MainWin(QMainWindow):
  def __init__(self):
    QMainWindow.__init__(self)
    self.resize(1000,1000)

    self.kernel = QtKernelManager()
    self.kernel.start_kernel()
    self.kernel.start_channels()

    self.console = IPythonWidget()
    self.console.kernel_manager = self.kernel

    self.setCentralWidget(self.console)

def main():
    app = QApplication(sys.argv)

    main_win = MainWin()
    main_win.show()
    main_win.activateWindow()

    app.exec_()

if __name__ == '__main__':
    main()

Trying to run this fails with the following error:

Traceback (most recent call last):
  File "./console_test.py", line 7, in <module>
    from IPython.frontend.qt.kernelmanager import QtKernelManager
  File "/usr/local/lib/python2.7/site-packages/IPython/frontend/qt/kernelmanager.py", line 5, in <module>
    from IPython.external.qt import QtCore
  File "/usr/local/lib/python2.7/site-packages/IPython/external/qt.py", line 17, in <module>
    sip.setapi('QString', 2)
 ValueError: API 'QString' has already been set to version 1

Rearranging the imports in the following order allows it to succeed:

from IPython.frontend.qt.kernelmanager import QtKernelManager
from IPython.frontend.qt.console.ipython_widget import IPythonWidget

from PyQt4.QtCore import Qt
from PyQt4.QtGui import QMainWindow, QApplication

Apparently, in order for the sip.setapi to be valid, a PyQt application can't have made any PyQt4 imports before importing from the IPython interface. For a simple one-file script like this there is no problem. However, adding an IPython widget into a large project would be difficult.

Is there any alternative to using sip.setapi?

@epatters
Copy link
Contributor

Unfortunately, there is not a good alternative. IPython is now using the v2 string API for both PySide and Python 3 compatibility reasons. This means that any Qt code using IPython must also use the v2 API.

To avoid having to order your imports in a silly way, you should make a call to sip.setapi before any Qt imports in the main script of your application. (You do not, of course, need to put a setapi call anywhere else.)

@Sharpie
Copy link
Author

Sharpie commented Feb 20, 2011

Any workarounds for projects where I don't have commit access to the main script? Or that contain significant amounts of Python code that use QString?

@takluyver
Copy link
Member

As far as I know, you have to pick one version of the API per project. So if IPython stuck with the v1 API, it couldn't be integrated with projects using the v2 API. No solution springs to mind, unfortunately. For an idea of how much code is affected in IPython, see the diff at #259.

@fperez
Copy link
Member

fperez commented Mar 13, 2011

I guess we'll need to close this one, since there isn't really anything we can do on our side. If anyone ever comes around with a better solution (doubtful) we can reopen and apply it.

This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants