Known Scripter Issues
First of all, please see the Scripter FAQ for a discussion of some common questions and problems.
If you have any proposed changes for the FAQ, feel free to put them here.
Error Importing Python Modules
I was getting an error in my python scripts when I was trying to import modules using commands such as:
I was running Scribus 126.96.36.199 on Windows XP. I had Python 2.4 already installed on my machine before I installed Scribus.
One of the helpful people on the Scribus IRC suggested the I delete the following files/folders from my Scribus installation:
File: python24.dll Folders: lib, dlls, tcl
After that, Scribus ran scripts using the original Python installation. I'm not sure if all these folders needed to go.
Conflict with Wx Python
Although, it seems pretty clear that the wx GUI system would not work within a scribus script, it's worse than that. Merely executing the command "import wx" locks up Scribus (version 188.8.131.52, Windows XP).
One thing that needs a bit more coverage than it currently gets in the FAQ is the issue of using GUIs. For now, I'll just link to a few of my mailing list posts on the topic. These posts are pretty technical answers, so I need to write up something a bit more readable later.
Some documentation on using PyQt with the extension script system has now been written and will appear in 1.2.2cvs shortly.
In brief summary, the main issues are:
- The use of sub-interpreters and the resulting problems with loading of some C extension modules, including PyGtk and PyQt
- The reason for this is, that PyQt needs the new Python GIL-locking mechanism which is itself incompatible with subinterpreters. The advice here is to don't use subinterpreters at all. In Kross we removed them. There for each script we create on the fly an own module and let it execute within that module where all modules are running within the same main interpreter. This works very well, provides a clean separated environment while scripts are still able to communicate with each other using the __main__ namespace. Another advantage is, that as long as the script runs aka has references to objects, it will stay alive what makes it very easy to e.g. run a script that uses PyQt to create QWidget's and embed them into the C++ application. A big disadvantage is, that it needs quit some time to do it right since one single error with the ref-counting of the PyObject's will result in scripts running forever aka till the main interpreter got shutdown. [sebsauer]
- Non-modal windows (that let you continue to interact with the app) can't be created in sub-interpreters because the script's data is destroyed when the script ends, and Scribus's execution cannot continue until the script ends.
- Event loop integration if you want to use PyGtk or Tkinter without "locking up" the Scribus GUI
- at least with PyQt this works pretty well for us. As example we are embedding for KSpread a QDockWidget that offers an interactive console + script-editor created within PyQt. See here the KSpread scripting tutorial. Again one of the main problems is to get right with the ref-counting. For example a script that blocks itself cause one QWidget keeps a reference to another QWidget that keeps a reference to the other (so, circular references) does block freeing the script. Python comes here with very bad aka none detecting functionality for such circular references :-( [sebsauer]
With the macro manager patches integrated into 1.2.2cvs, you can now use PyQt and create non-modal windows such as extra palettes by writing a script that is run from 'Load extension script'. The script does the setup, creates the window, then exits - but when it exits its data is not destroyed, and its windows continue to execute as part of the Qt event loop, calling Python functions when events are triggered.
- If GIL-locking is used and subinterpreters are not, then this will only happen if a script runs within an own thread what is not needed at all except long blocking operations like running a webserver in the background are done. For non-modal windows using PyQt, it's enough to just use the same event-loop the main-app runs in. If the with PyQt created QWidget then has the proper parent-widget (e.g. the qApp->mainWidget), then the script will also cleanup right. If for whatever reason an own thread is needed, then we solved this at KOffice by just connecting the thread with the qApp's destroyed()-signal and then shutdown the thread if it's emitted. That's thread-safe and works quit well. [sebsauer]
I've also been able to successfully use Tkinter to create windows in scribus without "locking up" the main interpreter. This involved hijacking the Scribus event loop and putting Scribus under the control of its embedded Python interpreter. Not pretty. Expect a cleaner solution involving the registration of timers to call other toolkits' event loops to come later.
It should be obvious by now that building Python GUIs for use in scribus is a non-trivial task. For now, stick to using Tkinter for most GUI work, or use PyQt with "load extension script" if you want to build new palettes and other things that hang around while you continue to work in Scribus.
Known PyQt issues and limitations
Please record any known issues with using PyQt in Scribus here.
- Threading may not work (ringerc)
- issues accessing the main window; qApp.mainWidget() returns a QWidget (will be solved in upcoming PyQt release)
- PyQt crashes scribus if run from a normal script
It's probably also worth checking out Extension script discussion, which will cover some more matters about the developing extension script support.