Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #96552 > unrolled thread

Putting the main program in a main function

Started by"ast" <nomail@invalid.com>
First post2015-09-14 09:13 +0200
Last post2015-09-14 17:32 +1000
Articles 3 — 3 participants

Back to article view | Back to comp.lang.python


Contents

  Putting the main program in a main function "ast" <nomail@invalid.com> - 2015-09-14 09:13 +0200
    Re: Putting the main program in a main function Nobody <nobody@nowhere.invalid> - 2015-09-14 08:25 +0100
    Re: Putting the main program in a main function Ben Finney <ben+python@benfinney.id.au> - 2015-09-14 17:32 +1000

#96552 — Putting the main program in a main function

From"ast" <nomail@invalid.com>
Date2015-09-14 09:13 +0200
SubjectPutting the main program in a main function
Message-ID<55f673b3$0$3342$426a74cc@news.free.fr>
Hi

I saw here http://inventwithpython.com/pygame/chapter3.html
a program where the main program is put in a function.

So the structure is:

def main():
   main code here

def f1():
    function 1 code

def f2():
   function 2 code

......

if __name__ == '__main__':
    main()



The author says that with this structure there are no
global variables (except when using "global' keyword)
and that the program can be loaded as a module without
be ran to test the function in the python shell.

is it advised to always write programs like that ?

thx

[toc] | [next] | [standalone]


#96553

FromNobody <nobody@nowhere.invalid>
Date2015-09-14 08:25 +0100
Message-ID<pan.2015.09.14.07.25.04.87000@nowhere.invalid>
In reply to#96552
On Mon, 14 Sep 2015 09:13:47 +0200, ast wrote:

> is it advised to always write programs like that ?

If global (module-scope) variables are initialised by main, then those
variables won't exist unless main() is run, which means that you can't use
it as a module, only as a script.

IMHO, global variables whose initial values can be evaluated without
depending upon or modifying external state should be initialised at the
top level.

If a module has variables which cannot be so initialised, the module needs
to provide an initialisation function which must be called explicitly by
any program or module which imports it.

[toc] | [prev] | [next] | [standalone]


#96554

FromBen Finney <ben+python@benfinney.id.au>
Date2015-09-14 17:32 +1000
Message-ID<mailman.516.1442215949.8327.python-list@python.org>
In reply to#96552
"ast" <nomail@invalid.com> writes:

> The author says that with this structure there are no global variables
> (except when using "global' keyword) and that the program can be
> loaded as a module without be ran to test the function in the python
> shell.
>
> is it advised to always write programs like that ?

Writing all the code in functions makes your code more reliably tested:
you can write a unit test that exercises the code and know whether it is
behaving correctly.

Writing all the code in functions makes your code more understandable:
the possible interactions between different parts of the program are
more explicitly and strictly defined.

So yes, it's advisable to write a ‘main’ function for the application
and keep to absolute minimum the ‘if __name__ == "__main__"’ block.

That said, your ‘main’ function can be slightly more self-contained. The
paradigm for invoking a command-line program is that its input
parameters are the process's command-line arguments, and its return
value is the process's exit status.

So you can write a ‘main’ function that explicitly allows those input
and output to be handled as for a normal function::

    import sys

    def main(argv=None):
        """ Mainline code for this module.

            :param argv: The sequence of command-line arguments used to
                invoke this program. Defaults to `sys.argv`.
            :return: ``None``.

            """
        if argv is None:
            argv = sys.argv

        try:
            handle_the_command_line(argv)
            do_various_things()

        except SystemExit as exc:
            exit_status = exc.code
        else:
            # No exit requested; return “success” status.
            exit_status = 0

        return exit_status

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

That way, the ‘if __name__ == "__main__"’ block will use the
conventional input (command-line arguments) and output (process exit
status); the rest of the application code may call ‘sys.exit’ or raise
‘SystemExit’ as normal; but your code will wrap it all up as the inputs
and outputs of the ‘main’ function, making it much easier to control for
testing.

Python's BDFL wrote an article many years ago describing this pattern
<URL:http://www.artima.com/weblogs/viewpost.jsp?thread=4829>, mine is a
small refinement of that.

-- 
 \         “It is the fundamental duty of the citizen to resist and to |
  `\          restrain the violence of the state.” —Noam Chomsky, 1971 |
_o__)                                                                  |
Ben Finney

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.python


csiph-web