run.main() 如何运行?

78 阅读2分钟

在 Python 中,我们可以使用 if __name__ == '__main__': 来指定一段代码只在脚本直接运行时执行,而不会在被导入时执行。在某些情况下,我们可能需要在一个脚本中运行另一个脚本,这时就需要用到 run.main() 函数。

解决方案

run.py 中,定义了 main() 函数,可以解析命令行参数并调用另一个脚本的 runTest() 函数。

def main(argv):
    useShell = False
    for x in range(len(sys.argv)):
        if sys.argv[x] in ['--shell', '-shell', '-s']:
            useShell = True
            del sys.argv[x]
            break

    if len(argv) < 2:
        print("Please specify a demo module name on the command-line")
        raise SystemExit

    name, ext  = os.path.splitext(argv[1])
    module = __import__(name)


    app = RunDemoApp(name, module, useShell)
    app.MainLoop()

在另一个脚本中,通过 if __name__ == '__main__': 来判断是否直接运行脚本,如果是,则调用 run.main() 函数来运行脚本。

if __name__ == '__main__':
    import sys,os
    import run
    run.main(['', os.path.basename(sys.argv[0])] + sys.argv[1:])

代码例子

以下是一个完整的例子:

run.py

#!/usr/bin/env python

import wx
import wx.lib.inspection
import wx.lib.mixins.inspection
import sys, os

# stuff for debugging
print("wx.version:", wx.version())
print("pid:", os.getpid())
##raw_input("Press Enter...")

assertMode = wx.PYAPP_ASSERT_DIALOG
##assertMode = wx.PYAPP_ASSERT_EXCEPTION


#----------------------------------------------------------------------------

class Log:
    def WriteText(self, text):
        if text[-1:] == '\n':
            text = text[:-1]
        wx.LogMessage(text)
    write = WriteText


class RunDemoApp(wx.App, wx.lib.mixins.inspection.InspectionMixin):
    def __init__(self, name, module, useShell):
        self.name = name
        self.demoModule = module
        self.useShell = useShell
        wx.App.__init__(self, redirect=False)


    def OnInit(self):
        wx.Log_SetActiveTarget(wx.LogStderr())

        self.SetAssertMode(assertMode)
        self.Init()  # InspectionMixin

        frame = wx.Frame(None, -1, "RunDemo: " + self.name, pos=(50,50), size=(200,100),
                        style=wx.DEFAULT_FRAME_STYLE, name="run a sample")
        frame.CreateStatusBar()

        menuBar = wx.MenuBar()
        menu = wx.Menu()
        item = menu.Append(-1, "&Widget Inspector\tF6", "Show the wxPython Widget Inspection Tool")
        self.Bind(wx.EVT_MENU, self.OnWidgetInspector, item)
        item = menu.Append(-1, "E&xit\tCtrl-Q", "Exit demo")
        self.Bind(wx.EVT_MENU, self.OnExitApp, item)
        menuBar.Append(menu, "&File")

        ns = {}
        ns['wx'] = wx
        ns['app'] = self
        ns['module'] = self.demoModule
        ns['frame'] = frame

        frame.SetMenuBar(menuBar)
        frame.Show(True)
        frame.Bind(wx.EVT_CLOSE, self.OnCloseFrame)

        win = self.demoModule.runTest(frame, frame, Log())

        # a window will be returned if the demo does not create
        # its own top-level window
        if win:
            # so set the frame to a good size for showing stuff
            frame.SetSize((640, 480))
            win.SetFocus()
            self.window = win
            ns['win'] = win
            frect = frame.GetRect()

        else:
            # It was probably a dialog or something that is already
            # gone, so we're done.
            frame.Destroy()
            return True

        self.SetTopWindow(frame)
        self.frame = frame
        #wx.Log_SetActiveTarget(wx.LogStderr())
        #wx.Log_SetTraceMask(wx.TraceMessages)

        if self.useShell:
            # Make a PyShell window, and position it below our test window
            from wx import py
            shell = py.shell.ShellFrame(None, locals=ns)
            frect.OffsetXY(0, frect.height)
            frect.height = 400
            shell.SetRect(frect)
            shell.Show()

            # Hook the close event of the test window so that we close
            # the shell at the same time
            def CloseShell(evt):
                if shell:
                    shell.Close()
                evt.Skip()
            frame.Bind(wx.EVT_CLOSE, CloseShell)

        return True


    def OnExitApp(self, evt):
        self.frame.Close(True)


    def OnCloseFrame(self, evt):
        if hasattr(self, "window") and hasattr(self.window, "ShutdownDemo"):
            self.window.ShutdownDemo()
        evt.Skip()

    def OnWidgetInspector(self, evt):
        wx.lib.inspection.InspectionTool().Show()


#----------------------------------------------------------------------------


def main(argv):
    useShell = False
    for x in range(len(sys.argv)):
        if sys.argv[x] in ['--shell', '-shell', '-s']:
            useShell = True
            del sys.argv[x]
            break

    if len(argv) < 2:
        print("Please specify a demo module name on the command-line")
        raise SystemExit

    name, ext  = os.path.splitext(argv[1])
    module = __import__(name)


    app = RunDemoApp(name, module, useShell)
    app.MainLoop()



if __name__ == "__main__":
    main(sys.argv)

script.py

import wx
import wx.grid as grid
import wx.lib.mixins.gridlabelrenderer as glr

#----------------------------------------------------------------------

class MyGrid(grid.Grid, glr.GridWithLabelRenderersMixin):
    def __init__(self, *args, **kw):
        grid.Grid.__init__(self, *args, **kw)
        glr.GridWithLabelRenderersMixin.__init__(self)


class MyRowLabelRenderer(glr.GridLabelRenderer):
    def __init__(self, bgcolor):
        self._bgcolor = bgcolor

    def Draw(self, grid, dc, rect, row):
        dc.SetBrush(wx.Brush(self._bgcolor))
        dc.SetPen(wx.TRANSPARENT_PEN)
        dc.DrawRectangleRect(rect)
        hAlign, vAlign = grid.GetRowLabelAlignment()
        text = grid.GetRowLabelValue(row)
        self.DrawBorder(grid, dc, rect)
        self.DrawText(grid, dc, rect, text, hAlign, vAlign)


class MyColLabelRenderer(glr.GridLabelRenderer):
    def __init__(self, bgcolor):
        self._bgcolor = bgcolor

    def Draw(self, grid, dc, rect, col):
        dc.SetBrush(wx.Brush(self._bgcolor))
        dc.SetPen(wx.TRANSPARENT_PEN)
        dc.DrawRectangleRect(rect)
        hAlign, vAlign = grid.GetColLabelAlignment()
        text = grid.GetColLabelValue(col)
        self.DrawBorder(grid, dc, rect)
        self.DrawText(grid, dc, rect, text, hAlign, vAlign)


class MyCornerLabelRenderer(glr.GridLabelRenderer):
    def __init__(self):
        import images
        self._bmp = images.Smiles.getBitmap()

    def Draw(self, grid, dc, rect, rc):
        x = rect.left + (rect.width - self._bmp.GetWidth()) / 2
        y = rect.top + (rect.height - self._bmp.GetHeight()) / 2
        dc.DrawBitmap(self._bmp, x, y, True)



class TestPanel(wx.Panel):
    def __init__(self, parent, log):
        self.log