473,399 Members | 2,858 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,399 software developers and data experts.

why a main() function?

I think I read a suggestion somewhere to wrap the code where a Python
script starts in a main() function, so one has

def main():
print "hi"

main()

instead of

print "hi"

What are the advantages of doing this?

Sep 18 '06 #1
19 28535

be*******@aol.com wrote:
I think I read a suggestion somewhere to wrap the code where a Python
script starts in a main() function, so one has

def main():
print "hi"

main()

instead of

print "hi"

What are the advantages of doing this?

I'm sure there are other reasons, but for me the most important is that
you can import your code into the interpreter and poke at it from there
without executing the script. Also, of course, you can re-use your
code as a module in another program.

-Ben

Sep 18 '06 #2
On 18 Sep 2006 12:40:00 -0700, be*******@aol.com <be*******@aol.comwrote:
I think I read a suggestion somewhere to wrap the code where a Python
script starts in a main() function, so one has

def main():
print "hi"

main()

instead of

print "hi"

What are the advantages of doing this?
It is useful both importating scripts without running them, for
debugging or reusing parts of them later, and also for adding small
test scripts to modules to allow them to be run for testing purposes.
Sep 18 '06 #3
be*******@aol.com wrote:
I think I read a suggestion somewhere to wrap the code where a Python
script starts in a main() function, so one has

def main():
print "hi"

main()

instead of

print "hi"

What are the advantages of doing this?
Refine this to:

def main():
print "hi"

if __name__ == "__main__":
main()

The advantage of the 'if __name__ ..' statement is that you can import the
script without running the 'main' code, e.g. from your unittest module.

Wrapping the main code in a function allows you to call this function from
your unittests and test it like any other function.

Additionally I do usually add an 'argv' argument to main() which I use
instead of sys.argv, so I can easily test it with different arguments.

--
Benjamin Niemann
Email: pink at odahoda dot de
WWW: http://pink.odahoda.de/
Sep 18 '06 #4
be*******@aol.com wrote:
I think I read a suggestion somewhere to wrap the code where a Python
script starts in a main() function, so one has

def main():
print "hi"

main()

instead of

print "hi"

What are the advantages of doing this?
Guido van Rossum himself can tell you:

http://www.artima.com/forums/flat.js...06&thread=4829

regards
Steve
--
Steve Holden +44 150 684 7255 +1 800 494 3119
Holden Web LLC/Ltd http://www.holdenweb.com
Skype: holdenweb http://holdenweb.blogspot.com
Recent Ramblings http://del.icio.us/steve.holden

Sep 18 '06 #5
Others have already told you the most important things.

There is another secondary advantage: the code inside a function runs
faster (something related is true for C programs too). Usually this
isn't important, but for certain programs they can go 20%+ faster.

Bye,
bearophile

Sep 18 '06 #6
Steve Holden <st***@holdenweb.comwrites:
be*******@aol.com wrote:
I think I read a suggestion somewhere to wrap the code where a
Python script starts in a main() function
[...]
What are the advantages of doing this?
Guido van Rossum himself can tell you:
http://www.artima.com/forums/flat.js...06&thread=4829
I read that one a while ago, and now have this in most of my programs:

def __main__(argv=None):
""" Perform the main function of this program """
from sys import argv as sys_argv
if argv is None:
argv = sys_argv

# preparation, e.g. set up environment

exit_code = None
try:
do_the_main_thing(argv) # or whatever the main step is
except SystemError, e:
exit_code = e.code

return exit_code

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

This allows me to import my program as a module, and treat the main
routine as a function (argv as input, exit_code as output), while the
code itself can do sys.exit() without needing to know that it's
wrapped up in a function.

It also encourages me to write code inside do_the_main_thing() that
gets its environment parameterised as input, instead of specifying
sys.argv and the like. This makes the code much easier to unit test.

The name __main__ was chosen because I saw hints some time ago that
Python 3000 might automate some of these semantics for a function with
that name. True or false?

--
\ "Crime is contagious ... if the government becomes a |
`\ lawbreaker, it breeds contempt for the law." -- Justice Louis |
_o__) Brandeis |
Ben Finney

Sep 19 '06 #7
On 18 Sep 2006 14:38:12 -0700,
be************@lycos.com wrote:
... There is another secondary advantage: the code inside a function
runs faster (something related is true for C programs too). Usually
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
this isn't important, but for certain programs they can go 20%+
faster.
Okay, I give up.

AFAIK, All C code must be inside a function, unless you count the
expressions in initializers.

So aside from certain CPU/MMU/OS/cache/etc. quirks, why would C code
inside a function run faster than C code outside a function? Compiler
optimizations because of const and restrict keywords don't count.

And what other C code *isn't* inside a function?

Regards,
Dan

--
Dan Sommers
<http://www.tombstonezero.net/dan/>
"I wish people would die in alphabetical order." -- My wife, the genealogist
Sep 19 '06 #8
Another advantage is that you can catch all the unhandled exceptions of
the entire program (it they occurs) by doing something like this:

def another_call():
raise SomeUnexpectedException # it will be catched in '__main__'

def call():
another_call()

def run():
call()

in __name__ == '__main__':
try:
run()
except:
# do cleanup
# log exit message
# exit

Sep 19 '06 #9
be************@lycos.com wrote:
Others have already told you the most important things.

There is another secondary advantage: the code inside a function runs
faster (something related is true for C programs too). Usually this
isn't important, but for certain programs they can go 20%+ faster.
I totally fail to see why that should be the case - for python as well as
for C.

So - can you explain that a bit more, or provide resources to read up on it?

Diez
Sep 19 '06 #10
On 9/19/06, Diez B. Roggisch <de***@nospam.web.dewrote:
I totally fail to see why that should be the case - for python as well as
for C.
If you put your code into a main() function, all the names that it
binds are in the function's local scope, whereas if the code is in the
module's top level, the names are bound to the module's global scope.
Access to locals is somewhat faster than access to globals.

--
Cheers,
Simon B,
si***@brunningonline.net,
http://www.brunningonline.net/simon/blog/
Sep 19 '06 #11
"Diez B. Roggisch" wrote:
>There is another secondary advantage: the code inside a function runs
faster (something related is true for C programs too). Usually this
isn't important, but for certain programs they can go 20%+ faster.

I totally fail to see why that should be the case - for python as well as
for C.

So - can you explain that a bit more, or provide resources to read up on it?
Python stores local variables in an indexed array, but globals in a dictionary.
Looking things up by index is faster than looking them up by name.

Not sure what the C thing is; C doesn't really support putting *code* outside
functions. Maybe he was thinking about static vs. auto variables ?

</F>

Sep 19 '06 #12
Diez B. Roggisch wrote:
be************@lycos.com wrote:
>Others have already told you the most important things.

There is another secondary advantage: the code inside a function runs
faster (something related is true for C programs too). Usually this
isn't important, but for certain programs they can go 20%+ faster.

I totally fail to see why that should be the case - for python as well as
for C.

So - can you explain that a bit more, or provide resources to read up on
it?
A trivial example (for Python):

$ cat main.py
def main():
x = 42
for i in xrange(1000000):
x; x; x; x; x; x; x; x; x; x
x; x; x; x; x; x; x; x; x; x
x; x; x; x; x; x; x; x; x; x

main()
$ time python main.py

real 0m0.874s
user 0m0.864s
sys 0m0.009s
$ cat nomain.py
x = 42
for i in xrange(1000000):
x; x; x; x; x; x; x; x; x; x
x; x; x; x; x; x; x; x; x; x
x; x; x; x; x; x; x; x; x; x
$ time python nomain.py

real 0m2.154s
user 0m2.145s
sys 0m0.009s
$

Now let's verify that global variables are responsible for the extra time:

$ cat main_global.py
def main():
global i, x
x = 42
for i in xrange(1000000):
x; x; x; x; x; x; x; x; x; x
x; x; x; x; x; x; x; x; x; x
x; x; x; x; x; x; x; x; x; x

main()
$ time python main_global.py

real 0m2.002s
user 0m1.995s
sys 0m0.007s
Peter

Sep 19 '06 #13
Fredrik Lundh wrote:
"Diez B. Roggisch" wrote:
>>There is another secondary advantage: the code inside a function runs
faster (something related is true for C programs too). Usually this
isn't important, but for certain programs they can go 20%+ faster.

I totally fail to see why that should be the case - for python as well as
for C.

So - can you explain that a bit more, or provide resources to read up on
it?

Python stores local variables in an indexed array, but globals in a
dictionary. Looking things up by index is faster than looking them up by
name.
Interesting. How is the index computed? I would have assumed that locals()
is somehow used, which is a dicht.

I can imagine enumerating left-hand-side names and trying to replace their
occurence with the index, falling back to the name if that is not
possible/the index isn't found. Does that come close?

Diez
Sep 19 '06 #14
"Diez B. Roggisch" <de***@nospam.web.dewrites:
Python stores local variables in an indexed array, but globals in a
dictionary. Looking things up by index is faster than looking them up by
name.

Interesting. How is the index computed? I would have assumed that locals()
is somehow used, which is a dicht.
They're static indexes assigned at compile time.
Sep 19 '06 #15
In <7x************@ruckus.brouhaha.com>, Paul Rubin wrote:
"Diez B. Roggisch" <de***@nospam.web.dewrites:
Python stores local variables in an indexed array, but globals in a
dictionary. Looking things up by index is faster than looking them up by
name.

Interesting. How is the index computed? I would have assumed that locals()
is somehow used, which is a dicht.

They're static indexes assigned at compile time.
Which BTW is the reason why ``locals()['answer'] = 42`` does not work
within functions. The dictionary isn't the dictionary that's used for
locals but a proxy just for read access.

Ciao,
Marc 'BlackJack' Rintsch

Sep 19 '06 #16
Diez B. Roggisch wrote:
Interesting. How is the index computed? I would have assumed that locals()
is somehow used, which is a dicht.

I can imagine enumerating left-hand-side names and trying to replace their
occurence with the index, falling back to the name if that is not
possible/the index isn't found. Does that come close?
yes, but there is no fallback: if a name inside a function is local or
not is decided once and for all by the compiler, using static analysis.
see:

http://pyref.infogami.com/naming-and-binding

</F>

Sep 19 '06 #17
Steve Holden wrote:
be*******@aol.com wrote:
>I think I read a suggestion somewhere to wrap the code where a Python
script starts in a main() function, so one has

def main():
print "hi"

main()

instead of

print "hi"

What are the advantages of doing this?
Guido van Rossum himself can tell you:

http://www.artima.com/forums/flat.js...06&thread=4829
Interesting. A lot of the suggestions he makes are unnecessary if you
use argparse_ or optparse, since they do much cleaner argument parsing
and error reporting.

I basically never write a main() function in the sense described here.
My code usually looks something like:

if __name__ == '__main__':
parser = _argparse.ArgumentParser(...)
parser.add_argument(...)
...
arguments = parser.parse_args()

function_that_actually_does_stuff(arguments.foo,
arguments.bar,
arguments.baz)

So my ``if __name__ == '__main__'`` block does just enough argument
parsing to be able to call a real function.

... _argparse: http://argparse.python-hosting.com/

STeVe
Sep 19 '06 #18
be*******@aol.com wrote:
I think I read a suggestion somewhere to wrap the code where a Python
script starts in a main() function, so one has
<snip>
What are the advantages of doing this?
Others have stated all the good ones, so I'll state a slightly dumber
one for us part time amateur hackers :)

If you start off writing all your python module inside a main function
then as you chop your code up into other functions (refactoring), the
code inside main is already at the proper indentation level for the new
top level functions. No more indenting it one level further to suit
the functions indentation.

--
Cheers
Anton

Sep 20 '06 #19
an********@gmail.com wrote:
be*******@aol.com wrote:
>I think I read a suggestion somewhere to wrap the code where a Python
script starts in a main() function, so one has

<snip>
>What are the advantages of doing this?

Others have stated all the good ones, so I'll state a slightly dumber
one for us part time amateur hackers :)

If you start off writing all your python module inside a main function
then as you chop your code up into other functions (refactoring), the
code inside main is already at the proper indentation level for the new
top level functions. No more indenting it one level further to suit
the functions indentation.
That is also true if you start by putting all the main code inside an 'if
__name__=="__main__":' block. Besides, how hard is it to select the code
and hit tab or whatever the 'indent region' command is in your editor?

FWIW, my scripts generally evolve through several stages.

So looking at one I wrote recently I see that it started with a few lines
at the outer level which quickly went inside a __name__=='__main__' block
(so I could prod functions in the script interactively). Then as it grew
larger the script moved into a main() function and some argument processing
appeared in the __main__ block (and all the support functions disappeared
into a separate module). Then I wanted some exception handling at the outer
level so now I have the __main__ block containing outer level exception
handling, and calling main() which does argument processing and calls
script() which contains the original script.

It may evolve further: main() is a bit too large at the moment, and I think
I want to move the original script into another module with a command line
argument to select between scripts. My point being that I don't have a hard
and fast rule: I do whatever seems to make the code read clearly at the
time.
Sep 20 '06 #20

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

4
by: wongjoekmeu | last post by:
Hello All, >From a book where I have learned C++ it says that each application must have at least one function which is the main() function. Now I have the source code of a C++ program from...
89
by: Sweety | last post by:
hi, Is main function address is 657. its show in all compiler. try it & say why? bye,
1
by: wayne.denier | last post by:
Ran across this well documented, nice looking library for C++ gaming called Amaltheia ( http://home.gna.org/amaltheia/ ), but they don't have a community :P. I'm not sure if anybody has used it...
5
by: PencoOdStip | last post by:
Do i have to have a main function? If i don't have a function called main,i get erors.Why do i have to have a function called main?
1
by: shiniskumar | last post by:
i go tto perform some validation while ck=liking a button without refreshing the value.. i used ajax.My code is as follows...on button click i call the function validateGridAdd(); Inside tat...
28
by: ravi | last post by:
Hello everybody, I am writing a small application which does some work before the user main function starts execution. I am trying to #define the main function. But the problem is that,
11
by: aarklon | last post by:
Hi all, I have heard many discussions among my colleagues that main is a user defined function or not. arguments in favour:- 1) if it is built in function it must be defined in some header...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.