run.main()如何工作?

时间:2013-12-18 06:48:49

标签: python

请解释以下语句如何运行Python脚本。此块中没有自定义函数调用:

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

让我粘贴整个脚本:

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 = log
        wx.Panel.__init__(self, parent, -1)

        ROWS = 27
        COLS = 15

        g = MyGrid(self, size=(100,100))
        g.CreateGrid(ROWS, COLS)

        g.SetCornerLabelRenderer(MyCornerLabelRenderer())

        for row in range(0, ROWS, 3):
            g.SetRowLabelRenderer(row+0, MyRowLabelRenderer('#ffe0e0'))
            g.SetRowLabelRenderer(row+1, MyRowLabelRenderer('#e0ffe0'))
            g.SetRowLabelRenderer(row+2, MyRowLabelRenderer('#e0e0ff'))

        for col in range(0, COLS, 3):
            g.SetColLabelRenderer(col+0, MyColLabelRenderer('#e0ffe0'))
            g.SetColLabelRenderer(col+1, MyColLabelRenderer('#e0e0ff'))
            g.SetColLabelRenderer(col+2, MyColLabelRenderer('#ffe0e0'))

        self.Sizer = wx.BoxSizer()
        self.Sizer.Add(g, 1, wx.EXPAND)


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

def runTest(frame, nb, log):
    win = TestPanel(nb, log)
    return win

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



overview = """<html><body>
<h2><center>GridLabelRenderer</h2>

The <tt>wx.lib.mixins.gridlabelrenderer</tt> module provides a mixin
class for wx.grid.Grid that enables it to have plugin renderers that
work like the normal cell renderers do.  If desired you can specify a
different renderer for each row or col label, and even for the little
corner label in the upper left corner of the grid.  When each of those
labels needs to be drawn the mixin calls the render's Draw method with
the dc and rectangle, allowing your renderer class do do just about
anything that it wants.

</body></html>
"""



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
#----------------------------------------------------------------------------
# Name:         run.py
# Purpose:      Simple framework for running individual demos
#
# Author:       Robin Dunn
#
# Created:      6-March-2000
# RCS-ID:       $Id: run.py 53286 2008-04-21 15:33:51Z RD $
# Copyright:    (c) 2000 by Total Control Software
# Licence:      wxWindows license
#----------------------------------------------------------------------------

"""
This program will load and run one of the individual demos in this
directory within its own frame window.  Just specify the module name
on the command line.
"""

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)

2 个答案:

答案 0 :(得分:4)

在文件run.py中有一个这样的声明:

def main(args):
    pass

您正在导入run,并调用main函数。

__name__ == '__main__'部分只是告诉python如果文件是import,则只有在作为脚本运行时才运行执行该代码。


我不确定run.py的内容,但

os.path.basename(sys.argv[0])

将为您提供当前正在调用的脚本的名称,因此我猜测它是将脚本名称和第一个参数(sys.argv[1])传递给run.main,这就是如何它知道如何运行脚本。

答案 1 :(得分:1)

检查run.py的内容。从您发布的内容来看,它几乎变得简单,因为您可以跟踪函数调用。

  1. run.main(['', os.path.basename(sys.argv[0])] + sys.argv[1:]):调用run模块中的main函数。您正在将脚本文件名传递给此。
  2. run.main内,代码正在导入您的包。
  3. 检查run.py中有一行说明:win = self.demoModule.runTest(frame, frame, Log())。这一行在脚本中调用函数runTest。尝试删除此功能,或重命名可能;执行将失败。
  4. 您的runTest会返回TestPanelrun.py中的函数调用mainloop()来设置窗口事件循环,从而运行您的脚本。
  5. HTH