Python global keyword vs. Pylint W0603 Python global keyword vs. Pylint W0603 python python

Python global keyword vs. Pylint W0603


Generalized use of global variables can make maintenance a nightmare, because they make tracing the flow of your program, and sometimes you get weird bug, because some module has read the variable and acted on its value before some other module changed the value of the variable (and this can result from inverting two import statements in some unrelated 3rd module). See also the wikipedia entry on Global variables.

This is why you should avoid mutable global variables, IMO, and why Pylint issues a warning (and probably should issue more of them. Detecting the use of the global keyword is just an easy way of spotting some of them).

Don't take me wrong: I am not saying you must not use global variables. Only that you should avoid using them. There are lots of legit cases for global variables in Python. As long as you don't get more than a couple W0603, you should fare OK.

Now, Logilab (the company maintaining Pylint, and where I used to work) once had to take over maintenance of a piece of > 50kloc of Python code, with heavy duplication and 100+ mutable global variables. And this was hell.

Solutions to work around global variables include:

  • adding a parameter to the functions which need to access the variable
  • using class attributes
  • using instance attributes (by passing the value you need to the constructor of the class)
  • centralizing mutable global values in a Configuration object which is build so that it is instantiated once at program startup (using environment variables, command line, configuration file...) and never mutated after this.


I would replace this:

the_file = Nonedef open_the_file(fname):    global the_file    the_file = open(fname)def write_to_the_file(data):    the_file.write(data)open_the_file("boo")write_to_the_file("Hi!")

with this:

class FileProgram(object):    def __init__(self):        self.the_file = None    def open_the_file(fname):        self.the_file = open(fname)    def write_to_the_file(data):        self.the_file.write(data)if __name__ == "__main__":    prog = FileProgram()    prog.open_the_file("boo")    prog.write_to_the_file("Hi!")

You might say, "that's too complicated for my simple task!" OK, then don't run pylint on your program. You can't ask that pylint understand that your program is too small to use good structure.


In python, a module sharing global data like this is pretty much a singleton. you could accomplish the same thing with a singleton class, or ask yourself whether there is any reason you actually need a singleton. If you don't need a singleton -- use a regular class (instance). If you do need a singleton, google/search SO to figure out which pattern you think will suit you best. Maybe you do want a module -- there is a niche for global -- Otherwise Guido would have cut it out of the language a long time ago -- That niche just happens to be pretty small...