Snake_Byte #31: What's in a __name__?

Perhaps you've seen some Python code that looks like this:

What in the world is up with that if block? Some programming languages such as C, Java, and Go require that you define a "main" function that acts as the entry point for a program. However, Python, like many scripting languages, executes a program by interpreting each line from top to bottom. When the interpreter encounters the if block above, it checks the special attribute __name__ to see if its value is '__main__'. This will be the case when the module is the first one loaded by the python interpreter, e.g. when the above code is executed with python snakebyte_whats_in_a_name1.py. So, while Python does not officially specify an entry point function that will be executed at run time, the above pattern is an idiomatic way of achieving the same goal.

Note that you could have a module as follows:

When you run that script the end result will be the same as before. However, the advantage of using the if __name__ block is that it allows the module to be imported from elsewhere without automatically running the main() function. It is generally advisable to use the if __name__ block, even if it is not strictly necessary, as that may prove useful later on. For instance, consider adding unit tests for functions defined in your script; the tests will need to import your module, but you do not want the full script to run when that happens.

And what if a module is not the entry point for the interpreter? Its __name__ value will be the full package path plus the module's base file name. So, if you imported a module foo/bar/lib.py, its __name__ would be 'foo.bar.lib'. This simple reflection technique is frequently used in conjunction with Python's logging package. While we won't get into the details of Python logging here, it is common to see something like this:

When you request a logger object from the logging library, you can specify a name for the logger. That can be any arbitrary string, but the recommended practice is to pass in the module's __name__ attribute. When the logging system is configured for output, the logger's identifier can be included; this makes tracking down issues in an application much easier, as you can quickly identify the module from which a logging statement came. Using the __name__ attribute to identify logger objects also makes it easier to configure different logging handlers for different levels of a package hierarchy, such as enabling debug logging only for a particular package. For more details, see the logging package documentation.

It's not just Python modules that have a __name__ attribute; classes and functions also have inspectable names. Consider the following script:

When you run this, the output will be:

MyClass
foo
bar

The last thing to note about __name__ is that it is actually a writable attribute:

That outputs:

truth
lie

It is generally not useful to overwrite the default value for __name__, but it is frequently done in a particular case: decorator functions. I will save discussion about decorators for another time, but if you're curious about the relation to the __name__ attribute I suggest reading up on the functools.wraps() function.

You can also find more information about special attributes in the Python data model documentation.

Leave a Reply

Your email address will not be published.