3

I use the built-in webserver from web.py and not apache like in this question: Global variable usage with web.py in Apache

I have this web service that takes a number as argument, adds it to an internal variable number and returns that variable.

Here's how the script looks like:

import web
import sys

urls = (
    '/(\d+)', 'Number'
)

class Number:
    def GET(self, parameter):
        # I want to read and write to the variable number here

        print "number in web service is " + str(number)

        number = number + int(parameter)
        return number


if __name__ == "__main__":
    #print sys.argv

    # I want to initialise the variable number here, based on command line parameter

    number = int(sys.argv[2]) if len(sys.argv) >= 3 else 0 # initialisation

    print "number init value " + str(number)

    app = web.application(urls, globals())
    app.run()

I start the server like so:

sudo python test.py 192.168.0.100 16

Where 16 is the initial value for the internal counter.

When executed like so:

http://192.168.0.100:8080/42

I get an UnboundLocalError: local variable 'number' referenced before assignment on this line

print "number in web service is " + str(number)

Ok, so I need global, because I don't want number to be a local variable of the service, I change to:

import web
import sys

urls = (
    '/(\d+)', 'Number'
)

class Number:
    def GET(self, parameter):
        # I want to read and write to the variable number here

        global number # number is not a lcoal variable

        print "number in web service is " + str(number)

        number = number + int(parameter)
        return number


if __name__ == "__main__":
    #print sys.argv

    # I want to initialise the variable number here, based on command line parameter

    number = int(sys.argv[2]) if len(sys.argv) >= 3 else 0 # initialisation

    print "number init value " + str(number)

    app = web.application(urls, globals())
    app.run()

Now I get a different error when calling the service on the same line NameError: global name 'number' is not defined. To fix this, I add an initialization at the top:

import web
import sys

urls = (
    '/(\d+)', 'Number'
)

number = 0 # assigning value to define variable

class Number:
    def GET(self, parameter):
        # I want to read and write to the variable number here

        global number # number is not a lcoal variable

        print "number in web service is " + str(number)

        number = number + int(parameter)
        return number


if __name__ == "__main__":
    #print sys.argv

    # I want to initialise the variable number here, based on command line parameter

    number = int(sys.argv[2]) if len(sys.argv) >= 3 else 0 # initialisation

    print "number init value " + str(number)

    app = web.application(urls, globals())
    app.run()

While I do not receive an error now, the logic is broken. While the initial print displays that number init value is 16, the other print does not have the same value, it says number in web service is 0.

Apparently, there are two separate number variables in my code. I found this answer that states that __main__ is a separate module. Now that explains the different values for number. However, when I try to add global to __main__, like so:

import web
import sys

urls = (
    '/(\d+)', 'Number'
)

number = 0 # assigning value to define variable

class Number:
    def GET(self, parameter):
        # I want to read and write to the variable number here

        global number # number is not a lcoal variable

        print "number in web service is " + str(number)

        number = number + int(parameter)
        return number


if __name__ == "__main__":
    #print sys.argv

    # I want to initialise the variable number here, based on command line parameter

    global number # I want that one global variable number
    number = int(sys.argv[2]) if len(sys.argv) >= 3 else 0 # initialisation

    print "number init value " + str(number)

    app = web.application(urls, globals())
    app.run()

The value is again 16 upon initialization and 0 on the service. I get a SyntaxWarning: name 'number' is assigned to before global declaration on that new line in __main__

So I got rid of the assignment on the top again, which wasn't really necessary in the first place. because the real initialization happens in __main__:

import web
import sys

urls = (
    '/(\d+)', 'Number'
)

class Number:
    def GET(self, parameter):
        # I want to read and write to the variable number here

        global number # number is not a lcoal variable

        print "number in web service is " + str(number)

        number = number + int(parameter)
        return number


if __name__ == "__main__":
    #print sys.argv

    # I want to initialise the variable number here, based on command line parameter

    global number # I want that one global variable number
    number = int(sys.argv[2]) if len(sys.argv) >= 3 else 0 # initialisation

    print "number init value " + str(number)

    app = web.application(urls, globals())
    app.run()

While that executes without warnings initially, I do get a NameError global name 'number' is not defined from the GET method.

How do I create a variable that I can set in __main__ and that I can also read and write to from a method of a class that's defined in the same file?

Community
  • 1
  • 1
null
  • 5,207
  • 1
  • 19
  • 35

1 Answers1

0

The problem is because of the auto-re-loader just put it on the top of the file and everything should work

import web
import sys



number = int(sys.argv[2]) if len(sys.argv) >= 3 else 0 #initialisation

urls = (
'/(\d+)', 'Number'
)

 ... #the rest of the file

You see, the re-loader will do "reload(yourmodule)" so the __main__ part won't be called again :(

Cheers

Yoav Glazner
  • 7,936
  • 1
  • 19
  • 36