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


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

Is there any advantage to using a main() in python scripts?

Started byJL <lightaiyee@gmail.com>
First post2013-12-11 01:55 -0800
Last post2013-12-11 16:22 -0500
Articles 10 — 8 participants

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


Contents

  Is there any advantage to using a main() in python scripts? JL <lightaiyee@gmail.com> - 2013-12-11 01:55 -0800
    Re: Is there any advantage to using a main() in python scripts? Ben Finney <ben+python@benfinney.id.au> - 2013-12-11 21:26 +1100
    Re: Is there any advantage to using a main() in python scripts? Chris Angelico <rosuav@gmail.com> - 2013-12-11 21:41 +1100
    Re: Is there any advantage to using a main() in python scripts? marduk@letterboxes.org - 2013-12-11 07:57 -0500
      Re: Is there any advantage to using a main() in python scripts? Roy Smith <roy@panix.com> - 2013-12-11 09:20 -0500
    Re: Is there any advantage to using a main() in python scripts? Roy Smith <roy@panix.com> - 2013-12-11 09:17 -0500
      Re: Is there any advantage to using a main() in python scripts? rusi <rustompmody@gmail.com> - 2013-12-11 06:24 -0800
    Re: Is there any advantage to using a main() in python scripts? bob gailer <bgailer@gmail.com> - 2013-12-11 10:42 -0500
    Re: Is there any advantage to using a main() in python scripts? Chris Angelico <rosuav@gmail.com> - 2013-12-12 02:49 +1100
    Re: Is there any advantage to using a main() in python scripts? Terry Reedy <tjreedy@udel.edu> - 2013-12-11 16:22 -0500

#61541 — Is there any advantage to using a main() in python scripts?

FromJL <lightaiyee@gmail.com>
Date2013-12-11 01:55 -0800
SubjectIs there any advantage to using a main() in python scripts?
Message-ID<32615c9a-b983-4399-bb55-6df6c230f247@googlegroups.com>
Python scripts can run without a main(). What is the advantage to using a main()? Is it necessary to use a main() when the script uses command line arguments? (See script below)

#!/usr/bin/python

import sys

def main():
    # print command line arguments
    for arg in sys.argv[1:]:
        print arg

if __name__ == "__main__":
    main()

[toc] | [next] | [standalone]


#61544

FromBen Finney <ben+python@benfinney.id.au>
Date2013-12-11 21:26 +1100
Message-ID<mailman.3880.1386757610.18130.python-list@python.org>
In reply to#61541
JL <lightaiyee@gmail.com> writes:

> Python scripts can run without a main(). What is the advantage to
> using a main()?

Modular code – that is, implementing the program functionality in small,
well-defined units with narrow, strictly-defined interfaces – is good
design.

Practical benefits include being able to easily use the code as part of
a larger program, and being able to easily unit-test all the program's
code.

> Is it necessary to use a main() when the script uses command line
> arguments? (See script below)
>
> #!/usr/bin/python
>
> import sys
>
> def main():
>     # print command line arguments
>     for arg in sys.argv[1:]:
>         print arg
>
> if __name__ == "__main__":
>     main()

Better design is to make the argument list a parameter to the ‘main’
function; this allows constructing an argument list specially for
calling that function, without ‘main’ needing to know the difference.

You'll also want to catch SystemExit and return that as the ‘main’
function's return value, to make it easier to use as a function when
that's needed.

    def main(argv=None):
        if argv is None:
            argv = sys.argv

        exit_code = 0
        try:
            command_name = argv[0]
            config = parse_command_args(argv[1:])
            do_whatever_this_program_does(config)
        except SystemExit, exc:
            exit_code = exc.code

        return exit_code

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

That way, the normal behaviour is to use the ‘sys.argv’ list and to
raise SystemExit (via ‘sys.exit’) to exit the program. But ‘main’ itself
can, without any further changes, be called as a function that receives
the command line as a parameter, and returns the exit code.

-- 
 \       “Faith, n. Belief without evidence in what is told by one who |
  `\   speaks without knowledge, of things without parallel.” —Ambrose |
_o__)                           Bierce, _The Devil's Dictionary_, 1906 |
Ben Finney

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


#61546

FromChris Angelico <rosuav@gmail.com>
Date2013-12-11 21:41 +1100
Message-ID<mailman.3881.1386758510.18130.python-list@python.org>
In reply to#61541
On Wed, Dec 11, 2013 at 9:26 PM, Ben Finney <ben+python@benfinney.id.au> wrote:
>         except SystemExit, exc:

For new code, you'd of course want to write that as:

except SystemExit as exc:

which is compatible with Python 2.6, 2.7, and 3.x, while the other
syntax is 2.x only.

ChrisA

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


#61564

Frommarduk@letterboxes.org
Date2013-12-11 07:57 -0500
Message-ID<mailman.3895.1386766655.18130.python-list@python.org>
In reply to#61541
I would agree with the previous post but also add that I've stopped
calling the main function "main()" and usually give it a more
descriptive name, such as "bake_cookies()" or whatever.  I think that
that makes it clearer what it's doing when used as a library and the 'if
__name__ == '__main__'" already implies that it is the "main" script
function.

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


#61575

FromRoy Smith <roy@panix.com>
Date2013-12-11 09:20 -0500
Message-ID<roy-E30525.09202911122013@news.panix.com>
In reply to#61564
In article <mailman.3895.1386766655.18130.python-list@python.org>,
 marduk@letterboxes.org wrote:

> I would agree with the previous post but also add that I've stopped
> calling the main function "main()" and usually give it a more
> descriptive name, such as "bake_cookies()" or whatever.  I think that
> that makes it clearer what it's doing when used as a library and the 'if
> __name__ == '__main__'" already implies that it is the "main" script
> function.

If you're writing a library that's meant to be imported by other 
scripts, then that makes sense.  I tend to use main() for things that 
are done when your script is run as a stand-alone program.  That usually 
involves things like parsing command-line arguments, and configuring 
logging, neither of which you'd want to do in an importable library.

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


#61574

FromRoy Smith <roy@panix.com>
Date2013-12-11 09:17 -0500
Message-ID<roy-6DF7ED.09173411122013@news.panix.com>
In reply to#61541
In article <32615c9a-b983-4399-bb55-6df6c230f247@googlegroups.com>,
 JL <lightaiyee@gmail.com> wrote:

> Python scripts can run without a main(). What is the advantage to using a 
> main()? Is it necessary to use a main() when the script uses command line 
> arguments? (See script below)
> 
> #!/usr/bin/python
> 
> import sys
> 
> def main():
>     # print command line arguments
>     for arg in sys.argv[1:]:
>         print arg
> 
> if __name__ == "__main__":
>     main()

No, it's not necessary, but it's a good idea.

For one thing, it lets you import your script without actually running 
it.  We recently tracked down a long-standing bug where some maintenance 
script we had started out with:

import os
os.environ['DJANGO_SETTINGS_MODULE'] = 'whatever'

somebody imported that script in another part of the system because 
there was some convenient definition that he wanted to reuse.  
Unfortunately, the act of importing the script changed the environment!

The fix was to move the setting of the environment variable to inside 
the main() routine.  If you always follow the rule that you always put 
all your executable code inside main(), you'll never run into problems 
like that.

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


#61576

Fromrusi <rustompmody@gmail.com>
Date2013-12-11 06:24 -0800
Message-ID<b028423f-42e3-40ed-8140-9515e2700267@googlegroups.com>
In reply to#61574
On Wednesday, December 11, 2013 7:47:34 PM UTC+5:30, Roy Smith wrote:
>  JL  wrote:

> > Python scripts can run without a main(). What is the advantage to using a 
> > main()? Is it necessary to use a main() when the script uses command line 
> > arguments? (See script below)
> > #!/usr/bin/python
> > import sys
> > def main():
> >     # print command line arguments
> >     for arg in sys.argv[1:]:
> >         print arg
> > if __name__ == "__main__":
> >     main()

> No, it's not necessary, but it's a good idea.

> For one thing, it lets you import your script without actually running 
> it.  We recently tracked down a long-standing bug where some maintenance 
> script we had started out with:

> import os
> os.environ['DJANGO_SETTINGS_MODULE'] = 'whatever'

> somebody imported that script in another part of the system because 
> there was some convenient definition that he wanted to reuse.  
> Unfortunately, the act of importing the script changed the environment!

> The fix was to move the setting of the environment variable to inside 
> the main() routine.  If you always follow the rule that you always put 
> all your executable code inside main(), you'll never run into problems 
> like that.

I guess these are important but somewhat advanced considerations.

For a beginner, its important to get that there is a bit of a pun here:
The function habitually called 'main' may be called that or anything else
It can have or not have an argument as Ben pointed out -- maybe more than 
one also.

The module name __main__ is however sacrosanct and hardwired into python.
The habit of connecting the one with the other is partly conventional and
partly unavoidable

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


#61586

Frombob gailer <bgailer@gmail.com>
Date2013-12-11 10:42 -0500
Message-ID<mailman.3904.1386776551.18130.python-list@python.org>
In reply to#61541
On 12/11/2013 4:55 AM, JL wrote:
> What is the advantage to using a main()?
In addition to what's been said I add:

It separates all the global activities: defining of functions and 
classes, importing modules, etc. from the "doing" the actual task of the 
program.

It also ensures that the defining all the classes and functions happens 
before referencing them (less "bookkeeping" for me).

These two allow me to write the main program first, and follow it with 
all the global stuff.

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


#61588

FromChris Angelico <rosuav@gmail.com>
Date2013-12-12 02:49 +1100
Message-ID<mailman.3906.1386776974.18130.python-list@python.org>
In reply to#61541
On Thu, Dec 12, 2013 at 2:42 AM, bob gailer <bgailer@gmail.com> wrote:
> It also ensures that the defining all the classes and functions happens
> before referencing them (less "bookkeeping" for me).
>
> These two allow me to write the main program first, and follow it with all
> the global stuff.

I prefer define-before-use for readability, even if it doesn't matter
to the language. It means that locating the source of something can be
found by going upward (or starting at the top and going down - first
hit should be the definition), and helps keep things organized.
Obviously it's not always possible (mutual recursion, for instance),
but it's a general rule of thumb that I like to maintain.

ChrisA

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


#61620

FromTerry Reedy <tjreedy@udel.edu>
Date2013-12-11 16:22 -0500
Message-ID<mailman.3934.1386796935.18130.python-list@python.org>
In reply to#61541
On 12/11/2013 5:26 AM, Ben Finney wrote:

> Better design is to make the argument list a parameter to the ‘main’
> function; this allows constructing an argument list specially for
> calling that function, without ‘main’ needing to know the difference.
>
> You'll also want to catch SystemExit and return that as the ‘main’
> function's return value, to make it easier to use as a function when
> that's needed.
>
>      def main(argv=None):
>          if argv is None:
>              argv = sys.argv
>
>          exit_code = 0
>          try:
>              command_name = argv[0]
>              config = parse_command_args(argv[1:])
>              do_whatever_this_program_does(config)
>          except SystemExit, exc:
>              exit_code = exc.code
>
>          return exit_code
>
>      if __name__ == "__main__":
>          import sys
>          exit_code = main(sys.argv)
>          sys.exit(exit_code)
>
> That way, the normal behaviour is to use the ‘sys.argv’ list and to
> raise SystemExit (via ‘sys.exit’) to exit the program. But ‘main’ itself
> can, without any further changes, be called as a function that receives
> the command line as a parameter, and returns the exit code.

In particular, it is easier to write tests when argv is a parameter.

-- 
Terry Jan Reedy

[toc] | [prev] | [standalone]


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


csiph-web