How does Python "read in" a program when you run it? For example, I don't understand why there wouldn't be a NameError: name 'cough' is not defined in the below code:
def main():
for i in range(3):
cough()
def cough():
print('cough')
if __name__ == '__main__':
main()
Basically, my question can also be stated as why do the above and below programs output the same thing:
def cough():
print('cough')
def main():
for i in range(3):
cough()
if __name__ == '__main__':
main()
Python is an interpreted language which is executed statement by statement
(thanks to viraptor's tip: when compiling to bytecode it happens on whole file + per function)
In this case below the program reads line by line and knows that the function cough() and main() are defined. and later when main() is called Python knows what it is and when main() calls cough() Python knows what it is as well.
def cough():
print('cough')
def main():
for i in range(3):
cough()
if __name__ == '__main__':
main()
In this other case (below) it is the same thing. just that Python learns what main() function is before cough(). Here you might wonder: "why won't python throw an error since it doesn't know what caugh() is inside main() ? " Good question my friend.
But as long as your function is defined before you call it everything is fine. Because remember Python won't "check" if a function is defined until you call it. so in this case even tho cough() is not defined when python is reading function main() it is ok because we didn't call main() until after cough() is defined below.
def main():
for i in range(3):
cough()
def cough():
print('cough')
if __name__ == '__main__':
main()
Hope this helps you understand Python better.
The piece of code preventing the error to happen is this one:
if __name__ == '__main__':
main()
because you are putting it at the end of the code, after python read all the code above.
If you try to write something like
def main():
for i in range(3):
cough()
if __name__ == '__main__':
main()
def cough():
print('cough')
All you are going to get is this:
NameError: name 'cough' is not defined
When Python encounters a function while executing your source code, it does not immediately run the function. Rather, it compiles the function into an executable code object, and waits until you actually call the function.
This means the only time Python checks that cough() is really defined, is when you call main(). And since Python does find a cough function when main is called, it does not raise an error.
In other-words: Python does not verify the names used in function actually exist until run-time, so you so allowed to use currently undefined variable names.
This is the same reason a function such as this doesn't raise an error when defined, but it does during run-time:
>>> def func():
a + b
>>> func # func was compiled...
<function func at 0x7f8ddd5d6488>
>>> func() # but we cannot call it.
Traceback (most recent call last):
File "<pyshell#9>", line 1, in <module>
func() # but we cannot call it.
File "<pyshell#7>", line 2, in func
a + b
NameError: name 'a' is not defined
>>>
Also note that if you try to call main before cough has been defined, you will get an error:
>>> def main():
for i in range(3):
cough()
>>> main()
Traceback (most recent call last):
File "<pyshell#13>", line 1, in <module>
main()
File "<pyshell#12>", line 3, in main
cough()
NameError: name 'cough' is not defined
>>>
This shows that Python relies on every name in your function to have already been defined whether globally or locally, before you attempt to use them.
Python reads from the top of your script to the bottom. In both examples, the cough() function is called after it has been defined.
When you defined main() with cough() inside, the cough() function is not actually run. It is not run until the last line - that is after they have already been defined.
That's because the real execution code is here
if name == 'main':
main()
when main() is called, both main and cough have been defined
Related
I need to execute the class name with functions inside it and execute the functions inside the class individually on run time by passing arguments.
Python code saved as test.py
import sys
import threading
from threading import Thread
class test():
def func1(self):
print('hi im func1')
def func2(self):
print('hi im func2')
def func3(self):
print('hi im func3')
def runall(self):
if __name__ == '__main__':
Thread(target=self.func1).start()
Thread(target=self.func2).start()
Thread(target=self.func3).start()
if __name__ == '__main__':
try:
run = test()
run.runall()
globals()[sys.argv[1]]()
except KeyError:
raise KeyError('Invalid Function Name Passed in Argument! refer the code for valid Name.')
Trying to execute all functions inside class:
Runtime Execution: c:\ > python test.py test
Passed but gave error on
File "test.py", line 180, in
globals()sys.argv[2]
TypeError: 'test' object is not callable
Trying to execute only particular functions inside the class
Runtime Execution: c:\ > python test.py func1
Keyerror is getting thrown.
Can someone guide me on how to execute complete class and individual functions inside the class at runtime?
The first step works by me (on python 3.7.2)
> python3 test.py test
hi im func1
hi im func2
hi im func3
However this is triggered by the run.runall() statement. What version of Python do you run? don't you have another test variable in your work-space ?
For the second point, solution inspired by here, you could get the individual methods of the class running like this:
if __name__ == '__main__':
try:
run = test()
run.runall()
#globals()[sys.argv[1]]()
getattr(test(), sys.argv[1])()
except KeyError:
raise KeyError('Invalid Function Name Passed in Argument! refer the code for valid Name.')
result:
> python3 test.py func1
hi im func1
hi im func2
hi im func3
hi im func1
It worked for me Now I can Execute all Functions and separate functions individually. Thanks All For Your support and guide!!
if __name__ == '__main__':
try:
if sys.argv[2]=='test':
run = test()
run.runall()
else:
getattr(test(), sys.argv[2])()
except KeyError:
raise KeyError('Invalid Function Name Passed in Argument! refer the code for valid Name.')
Although I've been using python for a while, and a common pattern you see is these two statements:
def main():
# Fancy code here
if __name__ == "__main__":
main()
My question is, why wouldn't you use this pattern instead?
if __name__ == "__main__":
# Fancy code here
Is this just in case you want to import main from another place? Or is there some other reason you might want to do this?
Another reason is to avoid populating the global scope with variables.
Consider this example:
def add_em(arg1, arg2):
return a + b
if __name__ == "__main__":
a = 2
b = 4
print(add_em(a, b))
Here, the add_em() function clearly has a bug: it should return arg1 + arg2, but since the a and b variables belong to the global scope, this bug will likely go undetected until add_em() is called from another context. Running the script gives no error:
$ python myscript.py
6
Using a main() function would likely detect this earlier:
def add_em(arg1, arg2):
return a + b
def main():
a = 2
b = 4
print(add_em(a, b))
if __name__ == "__main__":
main()
Now the error is detected right away:
$ python myscript.py
Traceback (most recent call last):
...
NameError: name 'a' is not defined
A function is reusable, you can call it from other code. Code under the if __name__ guard can't so be invoked.
It makes testing and encapsulation easier. All you need is
import module
module.main()
I am trying to work around a problem I have encountered in a piece of code I need to build on. I have a python module that I need to be able to import and pass arguments that will then be parsed by the main module. What I have been given looks like this:
#main.py
if __name__ == '__main__'
sys.argv[] #pass arguments if given and whatnot
Do stuff...
What I need is to add a main() function that can take argument(s) and parse them and then pass them on like so:
#main.py with def main()
def main(args):
#parse args
return args
if __name__ == '__main__':
sys.argv[] #pass arguments if given and whatnot
main(sys.argv)
Do stuff...
To sum up: I need to import main.py and pass in arguments that are parsed by the main() function and then give the returned information to the if __name_ == '__main_' part.
EDIT
To clarify what I am doing
#hello_main.py
import main.py
print(main.main("Hello, main"))
ALSO I want to still be able to call main.py from shell via
$: python main.py "Hello, main"
Thus preserving the name == main
Is what I am asking even possible? I have been spending the better part of today researching this issue because I would like to, if at all possible, preserve the main.py module that I have been given.
Thanks,
dmg
Within a module file you can write if __name__ == "__main__" to get specific behaviour when calling that file directly, e.g. via shell:
#mymodule.py
import sys
def func(args):
return 2*args
#This only happens when mymodule.py is called directly:
if __name__ == "__main__":
double_args = func(sys.argv)
print("In mymodule:",double_args)
One can then still use the function when importing to another file:
#test.py
import mymodule
print("In test:",mymodule.func("test "))
Thus, calling python test.py will result in "In test: test test ", while calling python mymodule.py hello will result in "In mymodule: hello hello ".
This question already has answers here:
How can I call a function within a class?
(2 answers)
Closed 6 years ago.
I am new in programming and I have faced a problem for which I can't find an answer... So here it is:
`class MyClass:
def printsmth():
print("Hello")
def main():
printsmth()
if __name__ == '__main__':main()`
I get an error which says :
Traceback (most recent call last):
File "untitled.py", line 1, in <module>
class MyClass:
File "untitled.py", line 6, in MyClass
if __name__ == '__main__':main()
File "untitled.py", line 5, in main
printsmth()
NameError: name 'printsmth' is not defined
Code included is just an example, but it is the same error that I get on my real code, if for example I would transfer my code from main() to if name == 'main' than it works perfectly. The thing is that I want to relaunch main() method in some parts of the code but I haven't even gone to that because I can't think of a solution to this error:/ Can you help me?
P.S I tried to move main() and if name == 'main' from MyClass and it didn't worked.
You are forgetting to pass self as the first parameter of your methods. Once you do this, you can callself.printsmth() as a method. Right now it's confused because you're calling it as a function rather than a method.
class MyClass:
def printsmth(self):
print("Hello")
def main(self):
self.printsmth()
I have a pice of code which looks like this
if __name__ == "__main__":
main()
def main():
print("hello")
However, when I try to run this code I get the error
NameError: name 'main' is not defined
Have I not defined the name in the first line of the function "def main()"?
You should define main before call it
def main():
print("hello")
if __name__ == "__main__":
main()
Have I not defined the name in the first line of the function "def main()"?
Yes, but Python hasn't executed that definition yet. Put the function definition before the call.