Substitute for tkinter.dooneevent - python

I am porting a program (VMD, Visual Molecular Dynamics), which is written in C++ and has both Python and TCL interpreters embedded, to Python 3.x. Most of its UI is hard coded using the TCL/TK framework and OpenGl, so UI refreshs are done manually. When the Python interpreter is running it is possible to dynamically create new windows and even add new menus to the main UI using Tkinter. In this case all TK events are flushed by periodically calling some code in the Python side (see below). This ensures that all updates are thread-safe and don't break the interpreter.
int PythonTextInterp::doTkUpdate() {
// Don't recursively call into dooneevent - it makes Tkinter crash for
// some infathomable reason.
if (in_tk) return 0;
if (have_tkinter) {
in_tk = 1;
int rc = evalString(
"import Tkinter\n"
"while Tkinter.tkinter.dooneevent(Tkinter.tkinter.DONT_WAIT):\n"
" pass\n"
);
in_tk = 0;
if (rc) {
return 1; // success
}
// give up
have_tkinter = 0;
}
return 0;
}
However the function tkinter.dooneevent was removed from Python 3 and I can not find a substitute for it. I tried calling the low-level Tcl_DoOneEvent(TCL_DONT_WAIT) but when I dynamically created a new window I ended up crashing the Python interpreter with the error Fatal Python error: PyEval_RestoreThread: NULL tstate.
The answers in tkinter woes when porting 2.x code to 3.x, 'tkinter' module attribute doesn't exist doesn't help since I don't have a list of all windows that may created by the user.
Does anyone have any suggestion on how to flush the TK events in this case? It could be either on the Python side or in C++.
Thanks in advance

It looks like this is equivalent:
root = tkinter.Tk()
# Here's your event handler. Put it in a loop somewhere.
root.tk.dooneevent(tkinter._tkinter.DONT_WAIT)
# I don't know if it's possible to access this method without a Tk object.
Now, I don't know how exactly to convert this into your code- do you have a root Tk object with which you can access dooneevent? I'm not at all familiar with python 2 tkinter so I don't know exactly how evenly my code maps to yours. However, I discovered this when I was doing something very similar to you- trying to integrate the tkinter event loop into the asyncio event loop. I was able to create a coroutine that calls this method in a loop, yielding each time (and sleeping occasionally), so that the GUI remains responsive without blocking the asyncio event loop with tkinter._tkinter.create().
#asyncio.coroutine
def update_root(root):
while root.tk.dooneevent(tkinter._tkinter.DONT_WAIT):
yield
EDIT: I just read your comment about not having a widget. I know that the root.tk object is a tkinter._tkinter.TkappType instance created by calling tkinter._tkinter.create, and I don't think it's global. I'm pretty sure it's the core Tcl interpreter. You might be able to create your own by calling create. While it isn't documented, you can look at its usage in tkinter.Tk.__init__

Related

Handling embedded Python interpreter calls with GIL and multi-threading

Constellation / Context:
A C++ Executable (1) which dynamically links a C++ shared library emb.so (2)
which in turn is running an embedded python interpreter (3) that calls custom python functions (4).
Embedding the Python interpreter (3) is happening by using pybind11.
A call to a Python function from C++ can be simplified as:
py::module::import("test").attr("my_func")();
The executable (1) has a main loop in which it can do some other work, but it will call the python function at regular intervals.
Observation:
Variant 1: If I block inside the python function, the python code executes smoothly and quickly, but the main executable loop is obviously blocked
Variant 2: If I create a python thread inside the python function to return from the function immediately, the main executable is running, but the python code is running extremely slow (I can watch the iterations of a for-loop with a print one by one)
Question:
Why is Variant 2 so slow and how can I fix it?
My guess is that this has something to do with the GIL, and I tried to release the GIL inside the wrapper emb.so before returning to the main loop, but I wasn't able to do this without a segfault.
Any ideas?
It turned out that this is very much related to the following question:
Embedding python in multithreaded C application
(see answer https://stackoverflow.com/a/21365656/12490068)
I solved the issue by explicitely releasing the GIL after calling embedded Python code like this:
state = PyGILState_Ensure();
// Call Python/C API functions...
PyGILState_Release(state);
If you are doing this in a function or other C++ scope and you are creating python objects, you have to make sure that the python object's desctructor is not called after releasing the GIL.
So don't do:
void my_func() {
gil_state = PyGILState_Ensure();
py::int_ ret = pymodule->attr("GiveMeAnInt")();
PyGILState_Release(gil_state);
return ret.cast<int>();
}
but instead do
void my_func() {
int ret_value;
gil_state = PyGILState_Ensure();
{
py::int_ ret = pymodule->attr("GiveMeAnInt")();
ret_value = ret.cast<int>();
}
PyGILState_Release(gil_state);
return ret_value;
}

How Tkinter font.families() function gets a list of available font?

I'm making GUI application using Tkinter and I'm using tkinter.font.families() for making pull down list of selecting fonts.
Now, I'm wondering how this function works
I tried reading the code but I can't understand it because of my lack of enough knowledge...
def families(root=None, displayof=None):
"Get font families (as a tuple)"
if not root:
root = tkinter._default_root
args = ()
if displayof:
args = ('-displayof', displayof)
return root.tk.splitlist(root.tk.call("font", "families", *args))
This is a code of the function(https://github.com/python/cpython/blob/c4928fc1a853f3f84e2b4ec1253d0349137745e5/Lib/tkinter/font.py#L180).
my qeustion is
What is the meaning of args = ('-displayof', displayof)?
Where does tk.call() function came from?(I can't find this function in Tk class)
How does tk.call("font", "families", *args) function works?
Thank you for reading my question.
What is the meaning of args = ('-displayof', displayof)?
Tkinter is a small python wrapper around a tcl interepreter which has the tk package installed. All of the actual work of creating widgets, querying fonts, etc, is done by the tcl/tk libraries.
Tcl/tk commands use a leading dash to represent an option name, and the option is typically followed by a value. This code is preparing to call a tcl function, so it is building up a list of arguments required by tcl.
In this specific case, it's adding the -displayof option if the displayof argument was passed to the function.
Where does tk.call() function came from?
It comes from a C-based library. It is defined in a file named _tkinter.c. More specifically, it's the function Tkapp_Call. It is a small wrapper that allows python to execute commands within an embedded tcl interpreter.
How does tk.call("font", "families", *args) function works?
The tk library has a command named font. From within a tcl interpreter you would call it with something like this:
font families
The code tk.call("font", "families", *args) is simply sending that command to the tcl interpreter.
The underlying tcl/tk library has platform-specific functions for dealing with fonts. See tkMacOSXFont.c, tkUnixFont.c, and tkWinFont.c.

Making a GDB debugging helper for the QUuid class

I'm using the QUuid class in my project and for testing and debugging purposes it would be very nice to see the QUuid objects in human readable form instead of their low-level form.
For some reason, the people at Qt have not included a dump method for this type so I attempted to create one on my own, following this documentation and this guide.
I'm not familiar with Python so unfortunately, I could not get something running. Could someone help me create such a function that does nothing more than display the output of QUuid::toString() in the value column of Qt Creator?
Edit:
Mitko's solution worked perfectly. I expanded it a bit so the details can still be read if so desired:
from dumper import *
import gdb
def qdump__QUuid(d, value):
this_ = d.makeExpression(value)
finalValue = gdb.parse_and_eval("%s.toString()" % (this_))
d.putStringValue(finalValue)
d.putNumChild(4)
if d.isExpanded():
with Children(d):
d.putSubItem("data1", value["data1"])
d.putSubItem("data2", value["data2"])
d.putSubItem("data3", value["data3"])
d.putSubItem("data4", value["data4"])
The following python script should do the job:
from dumper import *
import gdb
def qdump__QUuid(d, value):
this = d.makeExpression(value)
stringValue = gdb.parse_and_eval("%s.toString()" % this)
d.putStringValue(stringValue)
d.putNumChild(0)
The easiest way to use it with Qt Creator is to just paste these lines at the end of your <Qt-Creator-Install-Dir>/share/qtcreator/debugger/personaltypes.py file. In this case you can skip the first line, as it's already in the file.
As the personaltypes.py file is overwritten when you update Qt Creator you might want to put the script above in its own file. In that case you'll need to configure Qt Creator to use your file. You can do this by going to Tools > Options... > Debugger > GDB > Extra Debugging Helpers > Browse and selecting your file.
Note:
This script will only work inside Qt Creator, since we use its specific dumper (e.g. putStringValue).
We call QUuid::toString() which creates a QString object. I'm not sure exactly how gdb and python handle this, and if there is a need to clean this up in order to avoid leaking memory. It's probably not a big deal for debugging, but something to be aware of.

MS Access application opened from Python script can't quit if Tk() loop is called

I have stucked with a specific problem. I am working on Python script which reads data from MS Access database (.mdb) using VBA API and displays it in GUI tables using tkintertable module.
The problem is that after script terminates the MSACCESS.exe process is keeping alive in the process list.
When I comment mainloop() method for the root window the problem disappears.
Explicit call of access.quit() does not solve the problem. It makes it worse: the script terminates, but the MS Access process makes visible, I see it's window, but can't close it, because it appears more and more.
I removed all the unnecessary lines from the code to localize the problem:
#!C:\Python343\python
from comtypes.client import CreateObject
from tkinter import *
access = CreateObject('Access.Application')
root = Tk()
root.mainloop() # if I comment this line, everything works
# access.quit() - does not help: MS Access window gets visible and immortal
#
Can one give any clue of why this happens?
Thanks in advance for any advice.
Python version: 3.4.3.
MS Office: 2013.
Unfortunately, I can't switch to pypyodbc or other packages, because the script is big and it is not convenient to redesign it. Now it uses VBA API (OpenRecordSet, MoveFirst, MoveLast methods etc.), but pypyodbc does not mirror this API AFAIK.
Now I use a workaround (killing of the MSACCESS.EXE application). I will post it here. Probably, it will be useful for one who stuck with the same problem:
def close_by_force(app): # Took this function from https://stackoverflow.com/
# questions/10221150/cant-close-excel-completely-using-win32com-on-python,
# but had to redesign it to be usable to work with COM objects
import win32process
import win32gui
import win32api
import win32con
# Get the window's process id's
hwnd = app.hWndAccessApp()
t, p = win32process.GetWindowThreadProcessId(hwnd)
# Ask window nicely to close
win32gui.PostMessage(hwnd, win32con.WM_CLOSE, 0, 0)
# Allow some time for app to close
time.sleep(10) # not really necessary
# If the application didn't close, force close
try:
#print('pid='+str(p))
handle = win32api.OpenProcess(win32con.PROCESS_TERMINATE, 0, p)
if handle:
win32api.TerminateProcess(handle, 0)
win32api.CloseHandle(handle)
except:
pass
...
access = CreateObject('Access.Application')
DBEngine = access.DBEngine
db = DBEngine.OpenDatabase("C:\<my_db_path>")
.... some code (working with the database) ...
close_by_force(access.Application) # this is the crucial line
As I found in web, this problem is an old one and was discussed on different topics, but I don't see the exact solution anywhere, for example:
http://www.xtremevbtalk.com/showthread.php?t=298607
In C#, How should i close running threads ( Access DB )?
http://python-list.python.narkive.com/gCMlrB8M/using-excel-with-python
Found also that I can use something like
System.Runtime.InteropServices.Marshal.ReleaseComObject(access), but I can't found any link where may I get the related Python packages to use these classes.
--
Kind Regards,
Alexander.

ValueChanged signal for PyQt

I am using Python with PyQt5 for programming user interface.
Now I have a variable inside the UI class in Python(type: ctypes.c_long), and it is changed by calling a function inside a .dll file with ctypes. Python passes this variable with C++ by address.
MyVariable = ctypes.c_long(0)
MyUI.MyDll.MyFunc(ctypes.byref(MyUI.MyVariable))
And in C++ (.dll file), the codes could be like:
int MyFunc(int& my_var){
my_var = 5;
return 1;
}
Since I cannot emit signal inside the C++ code (.dll file), I wish to have an elegent way to detect the value changing of with variable to sync with a progress bar.
Thank you!

Categories