Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/logging/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/opencv/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 3.x 将Python记录器输出重定向到wxPython文本控件_Python 3.x_Logging_Wxpython - Fatal编程技术网

Python 3.x 将Python记录器输出重定向到wxPython文本控件

Python 3.x 将Python记录器输出重定向到wxPython文本控件,python-3.x,logging,wxpython,Python 3.x,Logging,Wxpython,我正在尝试将Python记录器的输出从外部脚本重定向到wxPython文本控件。GUI脚本在单独的线程中执行外部脚本。我曾尝试遵循本文中公认答案所述的方法,但未能使其按预期运行 以下是我迄今为止所做的尝试: # -*- coding: UTF-8 -*- #-------------------------------------------------------------------------------------------------- import logging from th

我正在尝试将Python记录器的输出从外部脚本重定向到wxPython文本控件。GUI脚本在单独的线程中执行外部脚本。我曾尝试遵循本文中公认答案所述的方法,但未能使其按预期运行

以下是我迄今为止所做的尝试:

# -*- coding: UTF-8 -*-
#--------------------------------------------------------------------------------------------------
import logging
from threading import Thread
import wx
import wx.lib.newevent as NE
#---------------------------------------------------------------------------------------------------
from module_sine import sin_fun
####################################################################################################
# Create event for the logger
wxLogEvent, EVT_WX_LOG_EVENT = NE.NewEvent()
#####################################################################################################
# Notification event for thread completion
UpdateEvent, EVT_UPDATE = NE.NewEvent()
#####################################################################################################
class wxLogHandler(logging.Handler):
    """
    A handler class which sends log strings to a wx object
    """
    def __init__(self, wxDest=None):
        """
        Initialize the handler
        @param wxDest: the destination object to post the event to 
        @type wxDest: wx.Window
        """
        logging.Handler.__init__(self)

        self.wxDest = wxDest
        self.level = logging.DEBUG

    def flush(self):
        """
        does nothing for this handler
        """
        pass

    def emit(self, record):
        """
        Emit a record.
        """
        try:
            msg = self.format(record)
            event = wxLogEvent(message=msg, levelname=record.levelname)            
            wx.PostEvent(self.wxDest, event)
        except (KeyboardInterrupt, SystemExit):
            raise
        except:
            self.handleError(record)
#####################################################################################################
class MyFrame(wx.Frame):
    def __init__(self, *args, **kwds):
        kwds["style"] = kwds.get("style", 0) | wx.DEFAULT_FRAME_STYLE | wx.STAY_ON_TOP
        wx.Frame.__init__(self, *args, **kwds)
        self.SetSize((400, 300))
        self.SetTitle("TEST")

        self.panel_1 = wx.Panel(self, wx.ID_ANY)

        sizer_1 = wx.BoxSizer(wx.VERTICAL)

        self.label_3 = wx.StaticText(self.panel_1, wx.ID_ANY, label="", style=wx.ALIGN_CENTER_HORIZONTAL)
        sizer_1.Add(self.label_3, 0, wx.ALL, 5)

        grid_sizer_2 = wx.FlexGridSizer(2, 1, 1, 1)
        sizer_1.Add(grid_sizer_2, 1, wx.EXPAND, 0)

        self.text_ctrl_3 = wx.TextCtrl(self.panel_1, wx.ID_ANY, "", style=wx.HSCROLL | wx.TE_MULTILINE | wx.TE_READONLY | wx.TE_RICH2)
        grid_sizer_2.Add(self.text_ctrl_3, 1, wx.EXPAND, 0)

        grid_sizer_2.Add((0, 0), 0, 0, 0)

        grid_sizer_1 = wx.FlexGridSizer(5, 2, 1, 1)
        sizer_1.Add(grid_sizer_1, 1, wx.EXPAND, 0)

        label_1 = wx.StaticText(self.panel_1, wx.ID_ANY, "x")
        grid_sizer_1.Add(label_1, 0, wx.ALL, 5)

        self.text_ctrl_1 = wx.TextCtrl(self.panel_1, wx.ID_ANY, "")
        grid_sizer_1.Add(self.text_ctrl_1, 0, 0, 0)

        label_2 = wx.StaticText(self.panel_1, wx.ID_ANY, "y")
        grid_sizer_1.Add(label_2, 0, wx.ALL, 5)

        self.text_ctrl_2 = wx.TextCtrl(self.panel_1, wx.ID_ANY, "")
        grid_sizer_1.Add(self.text_ctrl_2, 0, 0, 0)

        grid_sizer_1.Add((0, 0), 0, 0, 0)

        self.button_1 = wx.Button(self.panel_1, wx.ID_ANY, "Save")
        self.button_1.SetFocus()
        grid_sizer_1.Add(self.button_1, 0, 0, 0)

        grid_sizer_1.Add((0, 0), 0, 0, 0)

        self.button_2 = wx.Button(self.panel_1, wx.ID_ANY, "Start")
        grid_sizer_1.Add(self.button_2, 0, 0, 0)

        grid_sizer_1.Add((0, 0), 0, 0, 0)

        self.button_3 = wx.Button(self.panel_1, wx.ID_ANY, "Stop")
        grid_sizer_1.Add(self.button_3, 0, 0, 0)

        grid_sizer_2.AddGrowableRow(0)
        grid_sizer_2.AddGrowableCol(0)

        self.panel_1.SetSizer(sizer_1)

        self.Layout()

        self.Bind(wx.EVT_BUTTON, self.OnClick_Save, self.button_1)
        self.Bind(wx.EVT_BUTTON, self.OnClick_Start, self.button_2)
        self.Bind(wx.EVT_BUTTON, self.OnClick_Stop, self.button_3)

        self.Bind(wx.EVT_CLOSE, self.CloseWindow)

        # Set up event handler for any worker thread updates
        self.Bind(EVT_UPDATE, self.OnUpdate)
        # Indicate there is not any worker thread yet
        self.worker = None
        
        # Set up event handler for the logger
        self.Bind(EVT_WX_LOG_EVENT, self.onLogEvent)
        #------------------------------------------------------------------------------------------------
        # Logger 
        logging.basicConfig(level=logging.DEBUG, format='%(message)s')

        logger = logging.getLogger('testing')
        logger.setLevel(logging.DEBUG)
        # Text handler
        txthandler = wxLogHandler(self.text_ctrl_3)
        logger.addHandler(txthandler)
        txthandler.setLevel(logging.DEBUG)
        FORMAT = "%(message)s"
        txthandler.setFormatter(logging.Formatter(FORMAT))
        #------------------------------------------------------------------------------------------------
        self.button_2.Disable()
        self.button_3.Disable()
        #------------------------------------------------------------------------------------------------
        self.my_data = []
    #----------------------------------------------------------------------------------------------------
    def OnClick_Save(self, event):
        x = float(self.text_ctrl_1.GetValue())
        self.my_data.append(x)
        y = float(self.text_ctrl_2.GetValue())
        self.my_data.append(y)

        self.button_2.Enable()
        self.button_3.Enable()

        event.Skip()
    #----------------------------------------------------------------------------------------------------
    def OnClick_Start(self, event):
        """
        Run calc. in the thread
        """
        inp_val = self.my_data # entered values that will be passed to the thread
        if not self.worker:
            self.label_3.SetLabel('Run started')
            self.worker = WorkerThread(self, inp_val)
            self.button_2 = event.GetEventObject()
            self.button_2.Disable()
            self.label_3.SetLabel('Running ...')

        event.Skip()
    #------------------------------------------------------------------------------------
    def OnClick_Stop(self, event):
        """
        Abort calculation
        """
        if self.worker:
            self.label_3.SetLabel('Trying to abort run ...')
            self.worker.abort()

        event.Skip()
    #-----------------------------------------------------------------------------------
    def OnUpdate(self, event):
        """Show updates"""
        if event.data is None:
            # Thread aborted
            self.label_3.SetLabel('Run aborted')
            self.button_2.Enable()
            self.text_ctrl_3.SetValue("") # Clear any text transmitted to the text control when the thread is aborted.
            self.my_data.clear() # remove values from the list
        else:
            # Thread completed
            self.label_3.SetLabel('%s' % event.data)
            self.button_2.Enable()
            self.my_data.clear() # remove values from the list
        # In either event, the worker is done
        self.worker = None
    #------------------------------------------------------------------------------------------------
    def onLogEvent(self, event):
        '''
        Add event.message to text window
        '''
        msg = event.message.strip("\r")+"\n"
        self.text_ctrl_3.WriteText(msg)
        event.Skip()
    #------------------------------------------------------------------------------------------------
    def CloseWindow(self, event): # Not sure if this is a good implementation for the close window method.
        WorkerThread.abort(self)
        self.Destroy()
####################################################################################################
class WorkerThread(Thread):
    """Worker Thread Class."""
    #-----------------------------------------------------------------------------------------------
    def __init__(self, notify_win, inp_val):
        """Init Worker Thread Class."""
        Thread.__init__(self)
        self._notify_win = notify_win
        self.inp_val = inp_val
        self.daemon = True
        self._want_abort = False
        self.start()
    #-----------------------------------------------------------------------------------------------
    def run(self):
        """Run Worker Thread."""
        # This is the function executing in the new thread.
        [x, y] = self.inp_val
        sin_fun(x, y)
        if self._want_abort:
            wx.PostEvent(self._notify_win, UpdateEvent(data=None))
            return
        wx.PostEvent(self._notify_win, UpdateEvent(data='Run completed successfully!'))
    #-----------------------------------------------------------------------------------------------
    def abort(self):
        """Abort Worker Thread."""
        self._want_abort = True
####################################################################################################
class MyApp(wx.App):
    def OnInit(self):
        self.frame = MyFrame(None, wx.ID_ANY, "")
        self.SetTopWindow(self.frame)
        self.frame.Show()
        return True

if __name__ == "__main__":
    Test = MyApp(False)
    Test.MainLoop()
下面是我正在试验的外部脚本:

# -*- coding: UTF-8 -*-

import logging
import math

def sin_fun(x, y):
    logger = logging.getLogger('testing')
    for i in range(0, 2):
        a = (math.sin(x) + math.cos(y))*(x/y + i)
        logger.debug(a)
我使用的是Windows10、Python3.8.5和Wxpython4.1.0。 非常感谢您的帮助。 非常感谢