Bottom Page

Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
 [WxPython] Using thread in the wxPython
#1
I am one of the developer of a python2/3 package available on https://github.com/hildogjr/KiCost/
I am developing a GUI on wxPython 4.0.3 to call the CLI program part (kicost/kicost_gui.py file).

The call is made by a thread the execute the CLI function kicost(foo) inside the run(self), but in the thread have to update some GUI controls (process bars, text infos, log...). The GUI change parameters (text, label, process perceptual) work fine (or was before some changes on me code and update from wxPy4.0.1 to 4.0.3), now is returning this error:

Error:
[xcb] Unknown sequence number while processing queue [xcb] Most likely this is a multi-threaded client and XInitThreads has not been called [xcb] Aborting, sorry about that. python3: ../../src/xcb_io.c:274: poll_for_event: Assertion `!xcb_xlib_threads_sequence_lost' failed. Aborted (core dumped)
I think that is a bad configuration and call of the threading as I coded (bellow). Someone have some tips?

    def button_run(self, event):
        ''' @brief Call to run KiCost.'''
        event.Skip()
        def run_kicost_guide():
            '''Run the as a Thread out of the box wxPython'''
            self.m_gauge_process.SetValue(0)
            self.m_button_run.Disable()
            self.save_properties() # Save the current graphical configuration before call the KiCost motor.
            logger.log(DEBUG_OVERVIEW, 'Starting the KiCost scrape process.')
            self.run() # Run KiCost.
            init_distributor_dict() # Restore distributors removed during the execution of KiCost motor.
            self.m_button_run.Enable()
        def run_kicost_guide_action(): # Necessary to not freeze the GUI application during the scrapes.
            kicost_motor_thread = threading.Thread(target=run_kicost_guide)
            #kicost_motor_thread.setDaemon(1)
            kicost_motor_thread.start()
        wx.CallLater(10, run_kicost_guide_action) # Necessary to not '(core dumped)' with wxPython.
Quote
#2
It's been a long time since I last used wxpython, but you could perhaps use the module wxanythread from pypi. It defines a decorator @anythread which you can use to decorate methods interacting with the GUI that you want to call safely from any thread. The module is old, but its code is very short.
Quote
#3
I tested, unfortunately wxAnyThread is a Py2 code do wxPy3. I need a solution that works (also) in Py3 using wxPy4, since this code have to be long time supported and available to to P2/3.
Quote
#4
If you look in wxAnyThread, you'll see that, ignoring docstrings, it is only 60 meaningful lines of python in __init__.py. Don't you think you can adapt these 60 lines to work with Py3 and wxPy4?
Quote
#5
Yes, I think so. trying right now, the Py3 part is easy, but:

Error:
AttributeError: module 'wx' has no attribute 'Thread_IsMain'
Changing the attribute as in https://wxpython.org/Phoenix/docs/html/c...oenix.html I am getting a freeze GUI now.

    def button_run(self, event):
        ''' @brief Call to run KiCost.'''
        event.Skip()
        self.run_kicost_guide()

    @anythread
    def run_kicost_guide(self):
        '''Run the as a Thread out of the box wxPython'''
        self.m_gauge_process.SetValue(0)
        self.m_button_run.Disable()
        self.save_properties() # Save the current graphical configuration before call the KiCost motor.
        logger.log(DEBUG_OVERVIEW, 'Starting the KiCost scrape process.')
        self.run() # Run KiCost.
        init_distributor_dict() # Restore distributors removed during the execution of KiCost motor.
        self.m_button_run.Enable()
Is here some mistake mine on the call?
Quote
#6
It seems to me that your thread's main action is the self.run() and that this call does not use the wxpython GUI (tell me if I'm wrong). This main task of the thread must not go under anythread. The decorator is used to wrap parts that update the GUI. You could perhaps cut this in
def button_run(self, event):
    ''' @brief Call to run KiCost.'''
    event.Skip()
    self.run_kicost_guide()
 
@anythread
def foo(self):
    self.m_gauge_process.SetValue(0)
    self.m_button_run.Disable()
    self.save_properties() # Save the current graphical configuration before call the KiCost motor.
    logger.log(DEBUG_OVERVIEW, 'Starting the KiCost scrape process.')

def run_kicost_guide(self):
    '''Run the as a Thread out of the box wxPython'''
    self.foo()
    self.run() # Run KiCost.
    self.bar()

@anythread
def bar(self):
    init_distributor_dict() # Restore distributors removed during the execution of KiCost motor.
    self.m_button_run.Enable()
Quote
#7
Really in self.run() there are some GUI control read and update the GUI controls. So, I summarize all the code to it function and call as:

    def button_run(self, event):
        ''' @brief Call to run KiCost.'''
        event.Skip()
        self.run()
        #wx.CallLater(10, self.run) # Necessary to not '(core dumped)' with wxPython.

    @anythread
    def run(self):
        ''' @brief Run KiCost.'''
Also updated the wxAnyThread file (both available in https://github.com/hildogjr/KiCost/blob/...ost_gui.py).
The GUI and the process works, but during the process o the CLI (the GUI is used to run a command line based software), the GUI still freezing. About remove the main code/functionality out of the anythread: I changed the sys.out to output the log of the CLI program in a textControl so, even the CLI program start to interact with the GUI.
Quote
#8
(Aug-09-2018, 07:52 PM)hildogjr Wrote: but during the process o the CLI (the GUI is used to run a command line based software), the GUI still freezing
I think the GUI will stop freezing if you remove the call to the CLI program from the anythread context.
Quote
#9
Tried:

    def button_run(self, event):
        ''' @brief Call to run KiCost.'''
        event.Skip()
        def run_guide():
            args = self.run_before()
            cli_run(args)
            self.run_after(args.file_output)

@anythread
def self.run_before():
    ....
    return args
@anythread
def self.run_after(args):
Same behavior. Making something wrong here? (is because the args?)
Quote

Top Page

Possibly Related Threads...
Thread Author Replies Views Last Post
  Tkinter GUI is unresponsive in a thread sandarbhasthana 2 258 May-06-2019, 03:20 PM
Last Post: sandarbhasthana
  [WxPython] Adding a Window to a Button wxPython ShashankDS 4 345 Apr-23-2019, 06:53 PM
Last Post: Yoriz
  WxPython in web with a cgi server jttolleson 11 746 Mar-08-2019, 05:54 PM
Last Post: Weave
  run executable in separate process thread shift838 1 322 Jan-30-2019, 02:03 PM
Last Post: Alfalfa
  Thread/Signal LittleGrim13 2 685 Nov-30-2018, 02:35 PM
Last Post: LittleGrim13
  Problems using Wxpython Carles 1 582 Nov-28-2018, 03:09 PM
Last Post: Larz60+
  [Tkinter] Thread for serial Reading shows an error eabs86 0 435 Sep-20-2018, 01:44 AM
Last Post: eabs86
  Using 2 screens in wxpython Barrowman 1 773 Jun-27-2018, 07:43 PM
Last Post: Barrowman
  Trying to use code from WxPython GUI Toolkit Barrowman 3 976 Jun-26-2018, 05:43 PM
Last Post: nilamo
  A little idea to remember wxPython classes Sebastian_Adil 0 790 Mar-26-2018, 10:23 PM
Last Post: Sebastian_Adil

Forum Jump:


Users browsing this thread: 1 Guest(s)