This Pydon't walks you through the usages of the
__name__ dunder method and how to use it effectively.
(If you are new here and have no idea what a Pydon't is, you may want to read the Pydon't Manifesto.)
In this Pydon't we will take a look at the
If you Google it, you will find a ton of results explaining one
use case of the
__name__ attribute, so in this Pydon't
I'll try to tell you about another couple of use cases
so that you learn to use
__name__ effectively in your Python programs.
In this Pydon't, you will:
__name__to create “main” functions in Python;
__name__that many built-in objects get;
__name__is used in a convention involving logging; and
You can now get your free copy of the ebook “Pydon'ts – Write beautiful Python code” on Gumroad to help support the series of “Pydon't” articles 💪.
__name__ is a special attribute in Python.
It is special because it is a dunder attribute,
which is just the name that we give, in Python,
to attributes whose names start and end with a double underscore.
(I explain in greater detail what a dunder attribute/method
is in a previous Pydon't.)
You can look
__name__ up in the Python documentation,
and you will find two main results that we will cover here.
One of the results talks about
__main__ as a module attribute,
while the other result talks about
__main__ as an attribute
to built-in object types.
The most commonly known use case for
__name__ is as a module attribute,
__name__ to create “main” functions in Python.
What this means is that you can use
__name__ to determine programmatically
if your code is being ran directly as a script or if it is being imported
from another module.
How can we do this? Simple!
Go ahead and write the following line in your
Now open your command line and run the script:
> python print_name.py __main__
What this is showing you is that the attribute
was automatically set to
"__main__" when you ran your code
as a script.
This is relevant because that is not what happens when
you import your code from elsewhere.
As an example, go ahead and write the following line into your
Then go ahead and run this new Python script:
> python importer.py print_name
Where is that
"print_name" being printed from?
Well, the only
file, so that was definitely the place from where the printed value
Notice that some code got executed (and some things were
printed to the console) just by importing code from another module.
Also, notice that the value printed matches the name of the file
it came from.
Here, we see that
__name__ was automatically set to the name
of the file it was in (
print_name) when the code from
was imported from
So, we see that
__name__ takes on different values depending
on whether the code is ran directly as a script or imported
When you write code, you often write a couple of functions that help you solve your problem, and then you apply those functions to the problem you have at hands.
when I wrote some Python code to count valid passwords
in an efficient manner,
I wrote a class to represent an automaton in a file called
# automaton.py class Automaton: # ...
That class was problem-agnostic, it just implemented some basic
behaviour related to automatons.
It just so happened that that behaviour was helpful for me to solve
the problem of counting passwords efficiently, so I imported that
Automaton class in another file and wrote a little program
to solve my problem.
Thus, we can say that the majority of the times that I will use
the code in my
automaton.py file will be to import it from elsewhere
and to use it.
However, I also added a little demo of the functionality of the
Automaton class in the
Now, the problem is that I don't want this little demo to run
every time the
Automaton class is imported by another program,
so I have to figure out a way to only run the demo if the
automaton.py file is ran directly as a script...
The reason is that my demo code has some
from within another script...
Imagine importing a module into your program and suddenly
having a bunch of prints in your console!
Now, we can use
__name__ to avoid that!
We have seen that
__name__ is set to
"__main__" when a script
is ran directly, so we just have to check that:
# automaton.py class Automaton: # ... if __name__ == "__main__": print("Demo code.")
This is the most well-known use case of
This is why you will commonly see snippets like
if __name__ == "__main__": main()
It is just the Pythonic way of separating the functions and classes and other definitions, that might be useful for you to import later on, from the code that you only want to run if your program is the main piece of code being executed.
By the way, this global variable
__name__ really is a variable
that just gets initialised without you having to do anything.
But you can assign to it, even though it is unlikely that you
might need to do that.
Hence, this code is perfectly valid:
__name__ = "My name!" if __name__ == "__main__": # This will never run: print("Inside the __main__ if.")
__name__as an object type attribute
There is another Pythonic use case for the
another common usage pattern that employs
This pattern I will teach you about now doesn't have to do
with module attributes, but with object type attributes.
As you may be aware, all objects have a type that tells you “what” that object is.
Here are a couple of common types:
>>> type(0.5) <class 'float'> >>> type("hello") <class 'str'> >>> type(sum) <class 'builtin_function_or_method'>
Notice how the built-in
type tells you what is the class
of which the object is an instance.
"hello" is a string and that is why
which clearly contains the name of the class in there:
it is the
'str' in there, between the single quotes.
With this information, how would you implement a
function that only returns the string with the type name,
without the extra
Give it some thought.
Here is a possibility:
>>> def get_type_name(obj): ... return str(type(obj)).split("'") ... >>> get_type_name("hello") 'str' >>> get_type_name(sum) 'builtin_function_or_method'
Is this a good solution? I think we can definitely do better.
The documentation tells us that many built-in object types
and definitions come with its
which is “the name of the class, function, method, descriptor, or generator instance”.
Therefore, a better implementation of the
>>> def get_type_name(obj): ... return type(obj).__name__ ... >>> get_type_name("hello") 'str' >>> get_type_name(sum) 'builtin_function_or_method'
This is much shorter, much cleaner (doesn't have nested function calls, for example), and much easier to read, as the code says what it is doing. The name we picked for our function is good already, because it is easy to make an educated guess about what the function does, but it is much better if the body of the function itself makes it absolutely clear that we are getting what we want!
This ability of reaching out for the
__name__ of things is useful,
for example, when you want to print an error message because
you expected an argument of some type and, instead, you got something
__name__ you can get prettier error messages.
You can query the
__name__ of things other than built-in types.
You can also query the name of functions, for example:
>>> sum.__name__ 'sum' >>> get_type_name.__name__ 'get_type_name'
This might be relevant if you get ahold of a function in a programmatic way and need to figure out what function it is:
>>> import random >>> fn = random.choice([sum, get_type_name]) >>> fn.__name__ 'sum'
I don't think you are likely to receive a function from a
random.choice call, but this just shows how you can use
__name__ to figure out what function you are looking at.
Another great thing that already comes with a
your custom classes.
If you define a class,
__name__ will be a very clean way
of accessing the pretty class name without having to jump
through too many hoops or doing hacky string processing:
>>> class A(): ... pass ... >>> A <class '__main__.A'> >>> A.__name__ 'A' >>> a = A() >>> a >>> type(a) <class '__main__.A'> >>> type(a).__name__ 'A'
Similarly to the module
of types, functions, etc, can be assigned directly:
>>> type(a).__name__ 'A' >>> A.__name__ = "name..?" >>> type(a).__name__ 'name..?'
Sometimes this is useful, for example when you need to copy some metadata from one object to another.
I showed you what is the meaning that the
has, both as a module attribute and as an attribute of type objects,
and now I will show you how this knowledge can be put to practice.
I will be drawing my examples from the Python Standard Library,
as per usual.
If you take a look at the
you will find functions to deal with calendars in various ways.
If you inspect the source code, you will see that the implementation
of the module ends with the following two lines:
# From Lib/calendar.py in Python 3.9.2 if __name__ == "__main__": main(sys.argv)
In short, the module defines a series of functions that people might
want to import from elsewhere, but if the program is run directly,
then it will call the function
main, passing it in whatever
arguments the program received from the terminal.
As an example, try running the following on your command line:
> python -m calendar 2021 6 June 2021 Mo Tu We Th Fr Sa Su 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
This shows a great example of how a module might have something
interesting/useful to run if it is started as the main program.
main in the
calendar module implements a simple
command line interface with the
and thus the
main function is simply an entry point to the
code that the module already defined.
Just out of curiosity, the Python Standard Library for my installation
of Python 3.9.2 has 2280
.py files, and if you look for it,
you can find the line
if __name__ == "__main__": in 469 files,
a little over a fifth of the files...
So this really is a common pattern in Python!
Like I mentioned before, if you want to get the name of the type
of an object,
type(obj).__name__ is likely to be the way to go
about doing that.
An example of where this shows up is in the
enum modules gives support to enumerations in Python,
which are sets of symbolic names (members) bound to unique,
Here is an example enumeration:
>>> import enum >>> class Colour(enum.Enum): ... RED = "RED" ... GREEN = "GREEN" ... BLUE = "BLUE" ...
Now we have a way of talking about specific colours:
>>> Colour.RED <Colour.RED: 'RED'> >>> Colour.BLUE <Colour.BLUE: 'BLUE'>
Now, what if we want to delete one of the colours?
>>> del Colour.GREEN Traceback (most recent call last): File "<stdin>", line 1, in <module> File "C:\Program Files\Python39\lib\enum.py", line 382, in __delattr__ raise AttributeError("%s: cannot delete Enum member." % cls.__name__) AttributeError: Colour: cannot delete Enum member.
We can't delete
GREEN from the enum because the
isn't just like any other class attribute, it is actually an integral
part of the enumeration structure, and so the implementers of
this module guarded the class against this type of deletions.
The question is, how did they get the pretty name of my
I don't even have to show you the code, you can just look at the error
message above, that says we got an
AttributeError inside the
What was the line of code that produced this pretty error message?
It was the following line:
raise AttributeError("%s: cannot delete Enum member." % cls.__name__)
In this line,
cls is already a class,
something like this:
>>> Colour # <-- <enum 'Colour'> # <-- this is what `cls` is... # By the way, this is *not* a string.
So we could get its
__name__ directly and produce a pretty
error message, or at least as pretty as error messages go.
Another similar use case can be found in the
This module provides a function,
to convert a
Decimal number (from the
into an exact fraction.
From my description of the function maybe you understood it,
from_decimal function expects a
and errors out if the argument given is not such a thing:
>>> import fractions >>> fractions.Fraction.from_decimal("3") Traceback (most recent call last): File "<stdin>", line 1, in <module> File "C:\Program Files\Python39\lib\fractions.py", line 188, in from_decimal raise TypeError( TypeError: Fraction.from_decimal() only takes Decimals, not '3' (str)
Now the error message isn't enough because the code spans a couple
of different lines, but here is the type validation that the
from_decimal function performs:
# From Lib/fractions.py in Python 3.9.2 class Fraction(numbers.Rational): # ... @classmethod def from_decimal(cls, dec): """Converts a finite Decimal instance to a rational number, exactly.""" from decimal import Decimal if isinstance(dec, numbers.Integral): dec = Decimal(int(dec)) elif not isinstance(dec, Decimal): raise TypeError( "%s.from_decimal() only takes Decimals, not %r (%s)" % (cls.__name__, dec, type(dec).__name__)) return cls(*dec.as_integer_ratio())
Notice how the function takes a
dec and tries to convert it to
Decimal if the argument isn't a
Decimal but is easy to treat
That is why giving
3 to the function doesn't give an error:
>>> fractions.Fraction.from_decimal(3) Fraction(3, 1)
"3" is not a
numbers.Integral and it is also not
dec fails the tests and we end up with
raise TypeError( "%s.from_decimal() only takes Decimals, not %r (%s)" % (cls.__name__, dec, type(dec).__name__))
Notice how we even have two
__name__ usages here.
The first one is similar the example above with
and we take our
cls (that is already a class) and simply
ask for its name.
That is the part of the code that built the beginning of the message:
TypeError: Fraction.from_decimal() ... ^^^^^^^^
Then we print the value that actually got us into trouble, and that
is what the
dec is doing there:
TypeError: Fraction.from_decimal() only takes Decimals, not '3' ... ^^^
Finally, we want to tell the user what it is that the user passed in,
just in case it isn't clear from the beginning of the error message.
To do that, we figure out the type of
dec and then ask for its
__name__, hence the
type(dec).__name__ in the code above.
This is what produces the end of the error message:
TypeError: Fraction.from_decimal() only takes Decimals, not '3' (str) ^^^
"%r" in the string above have to do with string
formatting, a topic that is yet to be covered in these Pydon'ts.
Stay tuned to be the first to know when those
Pydon'ts are released.
type(obj).__name__ pattern is also very common.
In my 3.9.2 installation of the Python Standard Library,
it appeared 138 times in 74 different
cls.__name__ pattern also showed up a handful of times.
For the final code example I will be showing you a common convention
that is practised when using the
to log your programs.
logging module provides a
getLogger function to the users,
getLogger function accepts a
name string argument.
This is so that
getLogger can return a logger with the specified
On the one hand, you want to name your loggers so that, inside
huge applications, you can tell what logging messages came from where.
On the other hand, the
getLogger function always returns the same
logger if you give it the same name, so that inside a single module
or file, you don't need to pass the logger around,
you can just call
getLogger always with the same name.
Now, you want to get your logger by using always the same name and
you also want the name to identify clearly and unequivocally
the module that the logging happened from.
This shows that hand-picking something like
is a bad idea, as I am likely to pick
the same logger name as other developers picked in their code,
and so our logging will become a huge mess if our code interacts.
The other obvious alternative is to name it something specific to the module we are in, like the file name. However, if I set the logger name to the file name by hand, I know I will forget to update it if I end up changing the file name, so I am in a bit of a pickle here...
Thankfully, this type of situation is a textbook example of when the
__name__ attribute might come in handy!
__name__ attribute gives you a readable name that clearly
identifies the module it is from,
__name__ even means that your
logging facilities are likely to behave well if your code interacts
with other code that also does some logging.
This is why using
getLogger(__name__) is the recommended convention
in the documentation and that is why this pattern is used approximately
84% of the times!
(It is used in 103
.py files out of the 123
.py files that call
getLogger function in the Python Standard Library.)
Here's the main takeaway of this Pydon't, for you, on a silver platter:
__name__attribute is a dynamic attribute that tells you the name of the module you are in, or the name of the type of your variables.”
This Pydon't showed you that:
__name__is a module attribute that tells you the name of the module you are in;
__name__can be used to tell if a program is being ran directly by checking if
__name__to access the pretty name of the types of your objects;
__name__is an attribute that can be assigned to without any problem;
if __name__ == "__main__":is a very Pythonic way of making sure some code only runs if the program is ran directly;
type(obj).__name__is a simple way of accessing the type name of an object; and
__name__to set the name of loggers when using the
If you liked this Pydon't be sure to leave a reaction below and share this with your friends and fellow Pythonistas. Also, don't forget to subscribe to the newsletter so you don't miss a single Pydon't!
I hope you learned something new! If you did, consider following the footsteps of the readers who bought me a slice of pizza 🍕. Your contribution boosts my confidence and helps me produce this content for you.
calendar, https://docs.python.org/3/library/calendar.html [last accessed 29-06-2021];
enum, https://docs.python.org/3/library/enum.html [last accessed 29-06-2021];
__name__”, https://docs.python.org/3/search.html?q=name&check_keywords=yes&area=default [last accessed 29-06-2021];