overexchange
overexchange

Reputation: 1

Query on entry point annotation in 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?

Upvotes: 0

Views: 476

Answers (4)

user2357112
user2357112

Reputation: 280181

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.

Upvotes: 1

Oscar Bralo
Oscar Bralo

Reputation: 1907

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

Upvotes: 2

user1907906
user1907906

Reputation:

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

Upvotes: 0

Oleg Pryadko
Oleg Pryadko

Reputation: 1699

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:

Upvotes: 0

Related Questions