Query on entry point annotation in python - python

I am trying to understand the usage of #main annotation in python.
With the below python program,
def cube(x):
return x * x * x
def run_tests():
printf("Should be 1:", cube(1))
printf("Should be 8:", cube(2))
printf("Should be 27:", cube(3))
#main
def main():
print("Starting")
run_tests()
print("Ending.")
I get the following error:
PS C:\Users\MOHET01\Desktop> python.exe -i .\cube.py
Traceback (most recent call last):
File ".\cube.py", line 9, in <module>
#main
NameError: name 'main' is not defined
>>>
Function that is imported from ucb is as shown below:
def main(fn):
"""Call fn with command line arguments. Used as a decorator.
The main decorator marks the function that starts a program. For example,
interact()
#main
def my_run_function():
# function body
Use this instead of the typical __name__ == "__main__" predicate.
"""
if inspect.stack()[1][0].f_locals['__name__'] == '__main__':
args = sys.argv[1:] # Discard the script name from command line
print(args)
print(*args)
print(fn)
fn(*args) # Call the main function
return fn
My question:
Despite i define function with intrinsic name main, Why do i see this error?

I should use this:
def main():
#Do something
if __name__ == "__main__":
#Here use the method that will be the main
main()
I hope this helps

The #main decorator is implemented in a file your course provides, but you have not imported it. The page you linked says to use
from ucb import main, interact
to import the ucb.py features in your program.
As for why the error says name 'main' is not defined, that's because the function definition doesn't actually finish defining anything until the decorators execute. The reuse of the name main for both the decorator and the decorated function is confusing; the main in #main is a different function from the main you're defining in def main(): .... The main in #main is defined to run the decorated function if the file is run as a script, while the main in def main(): ... is the function to be run.
I would strongly recommend not using anything like this decorator when you don't have to. The standard way to perform the task the decorator performs is to write
if __name__ == '__main__':
whatever_function_you_would_have_put_the_decorator_on()
or if you want to handle command line arguments like the decorator would,
if __name__ == '__main__':
import sys
whatever_function_you_would_have_put_the_decorator_on(*sys.argv[1:])
The decorator is an attempt to hide the issues of sys.argv and __name__ so you don't have to know about them, but it has a problem. If you try to write something like this:
#main
def hello():
print(hello_string)
hello_string = 'Hi there.'
you'll get a NameError, because hello_string won't be assigned until after the decorator runs. If you continue to write Python beyond this course, you'll find that using if __name__ == '__main__' is less bug-prone and more understandable to other programmers than using a decorator for this.

You are using the function before it is defined. In other words, you need to define the main function higher up (in the document) than where you use it as a decorator:
def main():
pass
#main
def somefunction():
pass
The #main notation means the main function is being used to "decorate", or modify, another function. There are various articles on python decorators:
http://simeonfranklin.com/blog/2012/jul/1/python-decorators-in-12-steps/
http://www.artima.com/weblogs/viewpost.jsp?thread=240808
http://www.jeffknupp.com/blog/2013/11/29/improve-your-python-decorators-explained/

You can only use a decorator on a different function. Example:
def foo(f):
def inner():
print("before")
f()
print("after")
return inner
#foo
def bar():
print("bar")
if __name__ == "__main__":
bar()
Output:
before
bar
after

Related

Running python main with arguments programmatically

Hello I am having a piece of code that is like this root/main.py
def main():
parser = argparse.ArgumentParser(prog="my prog")
parser.add_argument('--param-1')
parser.add_argument('--param-2')
parser_result, unknown = parser.parse_known_args()
...(do stuff with params)
if __name__ == '__main__':
main()
and root/folder1/folder2/util.py
sys.path.append(os.path.dirname(os.path.realpath(__file__)) + "/../../../")
import main
...
main.main(param1, param2) //errors here for wrong arguments
My question is how do I trigger my main with params, there is a way to use java like reflection to trigger and read correct in main my arguments? (Ideally I need as less changes on main as possible)
Also used and worked:
os.system("python /root/main.py --param-1 '{param1}' --param-2'{param2}'")
But I prefer a solution that keeps the same context and is cleaner.
There is probably a way to do it like that, but the simplest way would be to add default parameters to main:
main.py
def main(param1="anything", param2="anything"):
# do something with parameters
if __name__ == "__main__":
main()
util.py
import main
main.main(param1, param2)

Trace a function to stop its execution by using settrace and inspect frame

Using work_block function, how can I use the inspect and sys libraries to stop print_text function from printing hello?
import inspect
import sys
def print_text():
print("Hello")
def main():
work_block()
print_text()
def work_block():
# stop print "Hello" from executing
if __name__ == '__main__':
main()
You don't need special libraries:
def work_block():
# stop print "Hello" from executing
global print_text
print_text = lambda : None
But why would you want to do that?
By the way, the trailing colons when calling functions in main() produce syntax errors.

Importing functions from in the same file as declared

I would like to place a function at the end of a script which is used in the script. This, of course, does not work as the function is not known yet.
Can I therefore import this funtion in the same script?
If I do it like the following, I get the error " ImportError: cannot import name:'subfunction' "
from the_script_in_use import subfuction
a=subfunction(b)
def subfunction(value)
do something
return a
One way to do this in Python is writing:
def main():
b = 5
a = subfunction(b)
print a
def subfunction(value):
a = value + 10
return a
if __name__ == '__main__':
main()
This way you can write your code in the order you like, as long as you keep calling the function main at the end.
You may use the statement :
if __name__ == '__main__':
Which will be executed if you run this file as a script. In your case:
def main_function()
a=subfunction(b)
def subfunction(value)
do something
return a
if __name__ == '__main__':
main_function()
Note there is no need to import your function.
Doing so you can order your fonction the way you want.
you can try to use pass :
def func1():
pass
func1()
def func1():
print "yes"
But this does not actually help you run the function.

How do decorators mark a function?

I was going throught the basic Flask tutorial which has the following code:
from flask import Flask
app = Flask(__name__)
#app.route("/")
def hello():
return "Hello World!"
if __name__ == "__main__":
app.run()
Also I went through the basics of Python decorators from many websites including Stackoverflow Decorators
I was of the assumption that in the previous code, the function hello will be changed and decorated, and for running the application I need to call the function hello() somewhere. How does Flask determine the name of the function it has to call.
Does just wrapping the function definition with a decorator somehow marks that function? If so, how?
For example in the below code, somewhere down the line I'm calling the function I've decorated:
def decorate(foo):
print("I'm doing a lot of important stuff right now")
def inner():
print("Some stuff 1")
foo()
print("Some stuff 2")
return inner
#decorate
def hello():
print("Hello")
hello()
In decorate, foo is the function you are decorating (in this case, hello). You can store the function in a list or dictionary somewhere, since it's a normal object.
For example:
decorated_functions = []
def decorate(foo):
def inner():
print("Some stuff 1")
foo()
print("Some stuff 2")
decorated_functions.append(inner)
return inner
#decorate
def hello():
print("Hello")
## The above is the same as:
# def hello():
# print("Hello")
# hello = decorate(hello)
print(decorated_functions[0] == hello) # prints True
decorated_functions[0]() # prints "Some stuff 1", "Hello", and "Some stuff 2"
hello() # same as above
Decorators are actually a very simple construct in Python. The following two examples are equivalent:
#foo
def bar():
pass
def bar():
pass
bar = foo(bar)
So your definition of hello in your first example is the equivalent to this:
def hello():
return "Hello World!"
hello = app.route("/")(hello)
The double function calls might be a bit confusing so lets rewrite it like this:
_tempfn = app.route("/")
hello = _tempfn(hello)
So it should be clear now that app.route isn't actually a decorator, it's a function that creates decorators. Now what isn't obvious is what the newly decorator does. Without looking at the source for Flash, it's likely that it adds the function hello to a dictionary member of a app. So app.route is implemented something like this:
class app(object):
def route(self, path):
def decorator(fn):
self.pathmap[path] = fn
return fn
return decorator
Note that this is pretty much a condensed version of the explanation given in the link that Jon Piparsky provided.
The decorator is simply registering the function in a lookup table. Decorators don't need to modify a function in any way, there are so many other useful things, decorators can do.
In fact, decorators in python
#some_decorator
def foo():
pass
are only a short form of
def foo():
pass
foo = some_decorator(foo)
and the function some_decorator can do anything with its arguments and can return any return value, but usually returns a function.

Python and indentation, having trouble getting started.

I have just started learning python and am getting caught up. I come from mostly C background.
class Alarm:
def timer():
def main():
print ("Timer has Started")
main()
I always get a silly error when I try to run this code:
alarm > python alarm.py
File "alarm.py", line 5
def main():
^
IndentationError: expected an indented block
You have an empty def
def timer():
use
def timer():
pass
instead.
Learn about the pass statement, main is usually not part of the class.
A global (module level) main() function is simpler than an Alarm.main() class method. Usually, main() functions come at module level.
class Alarm:
def timer():
pass
def main():
print ("Timer has Started")
main()
I think you want to use __init__ though, which is the constructor...
class Alarm:
def timer(self):
print('timer has started')
def __init__(self):
print('constructor')
self.timer()
x = Alarm()
constructor
timer has started
My example differs from the others in that I'm actually instantiating a new object.
Notes:
specify self as the first argument to any method defined in the class
__init__ is the method to define for the constructor
invoke the class by doing variableName = className() like you would invoke a function, no new keyword
if you have an empty function, use the pass keyword like def foo(self): pass
Invoking main() will give an undefined function error, as it is a Alarm method.
IMHO the right form you should use is the following:
class Alarm:
def timer():
pass
#staticmethod
def main():
print ("Timer has Started")
if __name__ == "__main__" :
Alarm.main()
try deindent main() and add pass to timer and define an init method:
class Alarm():
def __init__(self):
print ("Timer has Started")
<shell>$ Alarm()
Your timer function is not defined. (And your space/tab indentation may be mixed)
See the tutorial (classes) for more details on classes.
class Alarm:
def timer(self):
pass
def main(self):
print ("Timer has Started")
if __name__ == '__main__':
class_inst = Alarm()
class_inst.main()
If you getting into python read PEP8.
Also, using pylint helps, it will point out indentation and many other errors you'll run across before you 'execute' your code.
As others have pointed out, you have a syntax error because timer() has no body.
You don't need to use main() in python at all. Usually people use it to indicate that the file is the top level program and not a module to be imported, but it is just by convention
You may also see this idiom
def main():
blah blah
if __name__ == "__main__":
main()
Here __name__ is a special variable. If the file has been imported it will contain the module name, so the comparison fails and main does not run.
For the top level program __name__ contains "__main__" so the main() function will be run.
This is useful because sometimes your module might run tests when it is loaded as a program but you don't want those test to run if you are importing it into a larger program
In Python, you don't need to define everything as a class. There's nothing to encapsulate in this code, so there's no reason to define an Alarm class. Just have the functions in a module.
Thanks for all the help everybody. I was making a little alarm/timer to remind me to get up and take a walk every now and then. I got most of it working, and it works great. Checked it against a stop watch and it works great.
import time
def timer(num):
seconds = num*60
print (num , "minutes", seconds , "seconds")
while (seconds > 0):
print (seconds, "seconds")
time.sleep(1)
seconds = seconds-1
print ("Time to get up and take a WALK!!!!")
main()
def main():
number = input("Input time : ")
int(number)
timer(number)
if __name__ == '__main__':
main()

Categories