Why not place if __name__ == '__main__' at the beginning of the module? - python

Why is it standard in Python to have the main() function and the if __name__ == '__main__' check at the end of the block of code? It also seems standard for the abstraction of the functions to follow the same pattern upwards. What I mean is that the definition of the function to be executed by main() is above the main() and the definition of the functions inside that are above and so on..
That seems odd because when one opens the module to read the code, it ends up starting with low-level code and moves up to higher level functions. Isn't it hard to grasp what the module is doing that way?
Why not do the alternative? Have the if __name__ check at the top followed by the main() function, and so on. This way, one quickly glances at what the main() function does and understands what the code is about.

You can't call main() before it is defined. And main cannot call other functions before they are defined.
Example 1:
if __name__=='__main__':
main()
def main():
print("Hello")
This will error because main hasn't been defined yet at the point where you try and execute it.
Example 2:
def main():
hello()
if __name__=='__main__':
main()
def hello():
print("Hello")
This will error because main() is executed and tries to call hello before it is defined.
The if __name__=='__main__': which contains the call to main() works best at the end of the file so that everything that it needs has been defined before it is reached.
Where you put the main definition itself is more flexible, but putting it at the end (just before the if __name__=='__main__': block that calls it) makes as much sense as anywhere else.

The purpose of an if __name__ == '__main__': guard is to prevent a module from having side-effects when it's imported.
The fact that it is a module rather than a script implies that it will normally be used by other code importing the definitions from it, not executed directly. So given that, it makes sense that the functions, classes and constants appear first in the source code, since those are what users of the module will be importing (and hence, what they might want to see the source of).
So even if the code guarded by if __name__ == '__main__': doesn't rely on the definitions in the module already having been evaluated (which would be unusual), this part of the code is usually the least important to the users of the module, so it doesn't belong at the start of the file.

Related

Why do we put a main() function in python instead of just putting the code directly inside the "name == main" clause?

It is said to be a good practice to write the following block of code in your python modules:
if __name__ == '__main__':
# execute only if run as a script
main()
This prevents executing statements when you want to import this module into another program.
However, the curious thing over here is that main() function. We also need to put our code into an actual main method as follows:
def main()
# All code goes here
print("Inside main")
I feel that this is a roundabout way. Are there any benefits to creating a separate main() function and then calling it inside the if-clause?
Instead what is the harm in writing the code directly inside the if-clause?
if __name__ == '__main__':
# All code goes here
print("Inside main")
However, the curious thing over here is that main() function. We also need to put our code into an actual main method as follows:
Well, you dont need to do so. Actually if all you want is a plain script (something that's not going to be used as a module), you don't even "need" any function at all, you could as well put all your code directly at the top-level. BUT this will not make for clean, maintainable, testable code.
I feel that this is a roundabout way. Are there any benefits to creating a separate main() function and then calling it inside the if-clause
Quite simply the same benefits as you get from using functions (and modules and classes) to organize your code: clean, readable, testable, maintainable code. Just ask yourself how you are going to test your main function if you don't have a main function ?

Function results in program crash- no crash command [duplicate]

I have this code:
import sys
def random(size=16):
return open(r"C:\Users\ravishankarv\Documents\Python\key.txt").read(size)
def main():
key = random(13)
print(key)
When I try running the script, there are no errors, but nothing appears to happen. I expected it to print some content from the key file, but nothing is printed.
What is wrong? How do I make the code run?
You've not called your main function at all, so the Python interpreter won't call it for you.
Add this as the last line to just have it called at all times:
main()
Or, if you use the commonly seen:
if __name__ == "__main__":
main()
It will make sure your main method is called only if that module is executed as the starting code by the Python interpreter. More about that here: What does if __name__ == "__main__": do?
If you want to know how to write the best possible 'main' function, Guido van Rossum (the creator of Python) wrote about it here.
Python isn't like other languages where it automatically calls the main() function. All you have done is defined your function.
You have to manually call your main function:
main()
Also, you may commonly see this in some code:
if __name__ == '__main__':
main()
There's no such main method in python, what you have to do is:
if __name__ == '__main__':
main()
Something does happen, it just isn't noticeable
Python runs scripts from top to bottom. def is a statement, and it executes when it is encountered, just like any other statement. However, the effect of this is to create the function (and assign it a name), not to call it. Similarly, import is a statement that loads the other module (and makes its code run top to bottom, with its own global-variable context), and assigns it a name.
When the example code runs, therefore, three things happen:
The code for the sys standard library module runs, and then the name sys in our own module's global variables is bound to that module
A function is created from the code for random, and then the name random is bound to that function
A function is created from the code for main, and then the name main is bound to that function
There is nothing to call the functions, so they aren't called. Since they aren't called, the code inside them isn't run - it's only used to create the functions. Since that code doesn't run, the file isn't read and nothing is printed.
There are no "special" function names
Unlike in some other languages, Python does not care that a function is named main, or anything else. It will not be run automatically.
As the Zen of Python says, "Explicit is better than implicit". If we want a function to be called, we have to call it. The only things that run automatically are the things at top level, because those are the instructions we explicitly gave.
The script starts at the top
In many real-world scripts, you may see a line that says if __name__ == '__main__':. This is not "where the script starts". The script runs top to bottom.
Please read What does if __name__ == "__main__": do? to understand the purpose of such an if statement (short version: it makes sure that part of your top-level code is skipped if someone else imports this file as a module). It is not mandatory, and it does not have any kind of special "signalling" purpose to say where the code starts running. It is just a perfectly normal if statement, that is checking a slightly unusual condition. Nothing requires you to use it in a script (aside from wanting to check what it checks), and nothing prevents you from using it more than once. Nothing prevents you from checking whether __name__ is equal to other values, either (it's just... almost certainly useless).
You're not calling the function. Put main() at the bottom of your code.

Isn't checking if python script is NOT running in the main scope better?

Normally we are checking if script is running in the main scope
just like in Python docs: __main__, like this:
if __name__ == "__main__":
# execute only if run as a script
main()
This is simple and clear, but there is also a problem – indentation.
Whole def main(): have additional indent.
Does it hurt? Me – yes, a bit.
In Python we are particularly sensitive to line length.
This is important to respect space every time, not only
while writing 79th character.
Because of that I'm looking for good method to reduce
redundant indentation.
In my opinion – there is one. Also simple, clear and elegant.
if __name__ != "__main__":
exit()
# execute only if run as a script
Almost every of our ideas is wrong or already used somewhere,
so – I was looking for usage of this method and got nothing.
Looks like I'm the only one using that. I can't belief that at all,
but why then (if there is no hidden, tragic surprises) isn't it as popular
as it should be?
The major flaw with your proposal is that importing your module will cause the entire interpreter to exit. This means you can't import your module at all. If you try, the program will terminate.
Generally the purpose of the if __name__ == "__main__" block is to allow the module to be imported so you can use functions, classes, etc. inside it. This purpose is defeated by having the module exit when imported.
In addition, having the "extra indent" for the body of main is not just wasting line space. The body of main will be indented because it is the body of a function, and that function, like any other, can be called from elsewhere if the module is imported. This means someone else can import your module without running main, but later call main explicitly if they want.

Why doesn't the main() function run when I start a Python script? Where does the script start running (what is its entry point)?

I have this code:
import sys
def random(size=16):
return open(r"C:\Users\ravishankarv\Documents\Python\key.txt").read(size)
def main():
key = random(13)
print(key)
When I try running the script, there are no errors, but nothing appears to happen. I expected it to print some content from the key file, but nothing is printed.
What is wrong? How do I make the code run?
You've not called your main function at all, so the Python interpreter won't call it for you.
Add this as the last line to just have it called at all times:
main()
Or, if you use the commonly seen:
if __name__ == "__main__":
main()
It will make sure your main method is called only if that module is executed as the starting code by the Python interpreter. More about that here: What does if __name__ == "__main__": do?
If you want to know how to write the best possible 'main' function, Guido van Rossum (the creator of Python) wrote about it here.
Python isn't like other languages where it automatically calls the main() function. All you have done is defined your function.
You have to manually call your main function:
main()
Also, you may commonly see this in some code:
if __name__ == '__main__':
main()
There's no such main method in python, what you have to do is:
if __name__ == '__main__':
main()
Something does happen, it just isn't noticeable
Python runs scripts from top to bottom. def is a statement, and it executes when it is encountered, just like any other statement. However, the effect of this is to create the function (and assign it a name), not to call it. Similarly, import is a statement that loads the other module (and makes its code run top to bottom, with its own global-variable context), and assigns it a name.
When the example code runs, therefore, three things happen:
The code for the sys standard library module runs, and then the name sys in our own module's global variables is bound to that module
A function is created from the code for random, and then the name random is bound to that function
A function is created from the code for main, and then the name main is bound to that function
There is nothing to call the functions, so they aren't called. Since they aren't called, the code inside them isn't run - it's only used to create the functions. Since that code doesn't run, the file isn't read and nothing is printed.
There are no "special" function names
Unlike in some other languages, Python does not care that a function is named main, or anything else. It will not be run automatically.
As the Zen of Python says, "Explicit is better than implicit". If we want a function to be called, we have to call it. The only things that run automatically are the things at top level, because those are the instructions we explicitly gave.
The script starts at the top
In many real-world scripts, you may see a line that says if __name__ == '__main__':. This is not "where the script starts". The script runs top to bottom.
Please read What does if __name__ == "__main__": do? to understand the purpose of such an if statement (short version: it makes sure that part of your top-level code is skipped if someone else imports this file as a module). It is not mandatory, and it does not have any kind of special "signalling" purpose to say where the code starts running. It is just a perfectly normal if statement, that is checking a slightly unusual condition. Nothing requires you to use it in a script (aside from wanting to check what it checks), and nothing prevents you from using it more than once. Nothing prevents you from checking whether __name__ is equal to other values, either (it's just... almost certainly useless).
You're not calling the function. Put main() at the bottom of your code.

Why is the main() function not defined inside the if '__main__'?

You can often see this (variation a):
def main():
do_something()
do_sth_else()
if __name__ == '__main__':
main()
And I am now wondering why not this (variation b):
if __name__ == '__main__':
do_something()
do_sth_else()
Or at least this (variation c):
if __name__ == '__main__':
def main():
do_something()
do_sth_else()
main()
Of course the function calls inside main() might not be function calls, they just represent anything you might want to do in your main() function.
So why do people prefer variation a over the others? Is it just style/feeling or are there some real reasons? If possible, please also link sources.
Why limit your main() function to command line usage only?
By defining a main() function at module scope, you can now wrap your script and alter how it is called. Perhaps you want to set default arguments in sys.argv, perhaps you want to reuse the code in another script.
This is because there are two ways of using Python scripts. One from the command line and another when importing it from another script. When you run it from command line, you want to run main() function and when you import it you may not want to run main() function until you need it ( you just want to import main() ).

Categories

Resources