Python hangs on creating canvas (but works in root terminal)

I reinstalled Windows (7 Home Premium, 64-bit, UAC on (default)), installed Python 2.7.8 (32-bit version; 64-bit doesn’t work) and ROOT 5.34/21, set all the environmental variables and it worked… almost.

What is happening
Whenever I create a canvas (ie “a = TCanvas(“a”, “a”, 10, 10, 10, 10)”) or just draw something which then creates a canvas, the canvas window (which is opened by python.exe) freezes. It doesn’t matter whether I run it from IDLE or the Python command line. If I open root(.exe) and do the same, the canvas is created just fine.

Everything worked perfectly before the format (exact same versions), but now it only works as long as a canvas is not created.

What I tried
I tried installing VC++ 2012 update 4 and Cygwin just in case it was that (I did have a lot of shit installed before). It was not. %PATH% and %PYTHONPATH% have C:\root_v5.34.21\bin for both my user and all users. I tried an earlier version of Python and ROOT, I tried reinstalling them both several times, I tried rebooting (it’s a fresh install of Windows after all). I tried another graphics driver and running dxdiag in case it was a drawing issue, but I don’t think that anymore since I got it working in the ROOT terminal.

What could I be missing of libraries, drivers or other software? Is there any way to see an error log? Do you have any suggestions?

EDIT: Now that I think about it, could it be Python that has a problem with OpenGL? Probably not, since it still works in the root terminal…

Hi,

we’ve had trouble of graphics hanging on Windows since forever and have never been able to fully nail it. Part of the problem is lack of access to a Windows machine.

In ROOT.py, there is some workaround code for a special case to keep the graphics threads from blocking on eachother, which got rid of most issues: if sys.platform == 'win32': import thread _root.gROOT.ProcessLineSync('((TGWin32 *)gVirtualX)->SetUserThreadId(%ld)' % (thread.get_ident()))Make sure that this is executed. For all I know Windows may have moved on to win64. It should at some point, I guess.

Then there is an alternative, which was created for Mac, but may give trouble with IDLE. Set:import ROOT ROOT.PyConfig.StartGuiThread = 'inputhook'The reason why this may give trouble is b/c the inputhook was originally designed for Tk, and Tk is rather jealous of it: it won’t share the hook (PyROOT itself will).

Cheers,
Wim

Thanks for your help.

It did, however, not work. The first snippet makes no difference. The second does seem to make it threaded so it closes when the script ends.

The canvas is still not responding.

It’s funny though. I didn’t have a problem before, and no one else in my class has had any issues like this. Even the teacher hasn’t (to the best of his memory) experienced this. Windows is funny like that.

Anyhow, if it all fails in the end, I can resort to a virtual machine.

Hi,

[quote=“Daniel-Dane”]The second does seem to make it threaded so it closes when the script ends.[/quote]sorry, but what does that mean? The python interpreter closes when a script ends, unless explicitly kept alive with ‘-i’ for a prompt, or something like ‘q = raw_input("enter anything to quit ")’ to make it wait for input.

As for the first, I’m still curious what on Win7, this results:import sys print sys.platform
Thanks,
Wim

Sorry, I thought the snippet put the graphcis in a separate thread so as not to block the message queue. And yes, using raw_input keeps it all running until a key is pressed. But without that snippet, python freezes and I have to kill the python.exe process. That’s why I interpreted that as the message queue of the main thread not being blocked when the second snippet is executed.

I mainly run the scripts from cmd with “python test.py” and not using IDLE at all.

And for the platform, it’s still ‘win32’.

Hi,

no, the snippet already exists in ROOT.py: it’s a special case b/c there’s a thread in ROOT itself to prevent the (ROOT) CLI from starving. PyROOT always starts a GUI thread, too, except when disabled or the ‘inputhook’ option is used. I just wanted to make sure it’s executed, but with sys.platform indeed being win32, that should be all good.

With the inputhook, the python interpreter will cause updates on the main thread through the inputhook callback. I.e. one thread less.

Cheers,
Wim

Alright, close enough. :slight_smile:

And don’t worry, I tried without the if statement. So, what is left for me to try?

Hi,

sorry, I’m quickly running out of ideas. The only one left is to run the updates from the main thread (since it seems that you do not plan on having the prompt and the canvas at the same time). However, the inputhook option basically already does that.

Anyway, add this to the end of the script:if __name__ == '__main__': import time gSystemProcessEvents = ROOT.gSystem.ProcessEvents while 1: gSystemProcessEvents() time.sleep( 0.01 )
There is an alternative, which is to open the TCanvas on the GUI thread (by setting PyConfig.GUIThreadScheduleOnce), but as the option says, that only works once.

Beyond that, there’s nothing I can think of. Maybe one day I’ll get access to a Windows machine again.

Cheers,
Wim

Well, that actually does it! Thank you! It’s just sad that I need to do this to all scripts from now on (and make sure it doesn’t run on the other computers).

Begin the script with

import ROOT ROOT.PyConfig.StartGuiThread = 'inputhook'

End the script with

if __name__ == '__main__': import time gSystemProcessEvents = ROOT.gSystem.ProcessEvents while 1: gSystemProcessEvents() time.sleep( 0.01 )

Hi,

well, that’s something …

But the inputhook is safe on all platforms, and because both it and the gSystem.ProcessEvents() callback are initiated in python, they are mutually excluded by the GIL, and thus safe, too.

Cheers,
Wim