Locked learning resources

Join us and get access to thousands of tutorials and a community of expert Pythonistas.

Unlock This Lesson

Locked learning resources

This lesson is for members only. Join us and get access to thousands of tutorials and a community of expert Pythonistas.

Unlock This Lesson

Executing a Module

In this lesson, you’ll learn about executing a module as a script. Any .py file that contains a module is essentially also a Python script, and there isn’t any reason it can’t be executed like one.

Here’s mod.py, as it was defined earlier:

Python
s = "Computers are useless. They can only give you answers."
a = [100, 200, 300]

def printy(arg):
    print(f'arg = {arg}')

class Classy:
    pass

This can be run as a script:

Shell
$ python3 mod.py

There are no errors, so it apparently worked. Granted, it’s not very interesting. As it is written, it only defines objects. It doesn’t do anything with them, and it doesn’t generate any output.

Let’s modify the above Python module so it does generate some output when run as a script:

Python
s = "Computers are useless. They can only give you answers."
a = [100, 200, 300]

def printy(arg):
    print(f'arg = {arg}')

class Classy:
    pass

print(s)
print(a)
printy('Good Day Sir!')
x = Classy()
print(x)

Now it should be a little more interesting:

Shell
$ python3 mod.py
Computers are useless. They can only give you answers.
[100, 200, 300]
arg = Good Day Sir!
<__main__.Classy object at 0x10f7a35f8>

Unfortunately, now it also generates output when imported as a module:

Python
>>> import mod
Computers are useless. They can only give you answers.
[100, 200, 300]
arg = Good Day Sir!
<__main__.Classy object at 0x111324748>

This is probably not what you want. It isn’t usual for a module to generate output when it is imported. Wouldn’t it be nice if you could distinguish between when the file is loaded as a module and when it is run as a standalone script? Ask and ye shall receive!

When a .py file is imported as a module, Python sets the special dunder variable __name__ to the name of the module. However, if a file is run as a standalone script, __name__ is (creatively) set to the string '__main__'. Using this fact, you can see which is the case at run-time and change behavior accordingly:

Python
s = "Computers are useless. They can only give you answers."
a = [100, 200, 300]

def printy(arg):
    print(f'arg = {arg}')

class Classy:
    pass

if (__name__ == '__main__'):
    print(s)
    print(a)
    printy('Good Day Sir!')
    x = Classy()
    print(x)

Now, if you run as a script, you get output:

Shell
$ python3 mod.py
Computers are useless. They can only give you answers.
[100, 200, 300]
arg = Good Day Sir!
<__main__.Classy object at 0x100a5d5f8>

But if you import as a module, you don’t:

Python
>>> import mod
>>> dir()
['__builtins__', '__doc__', '__loader__', '__name__', '__package__',
'__spec__', 'help', 'mod']
>>> __name__
'__main__'
>>> mod.__name__
'mod'

Modules are often designed with the capability to run as a standalone script for testing the functionality that is contained within the module. This is referred to as unit testing. For example, suppose you have created a module fact.py containing a factorial function, as follows:

Python
def fact(n):
    return 1 if n == 1 else n * fact(n-1)

if (__name__ == '__main__'):
    import sys
    if len(sys.argv) > 1:
        print(fact(int(sys.argv[1])))

You can treat the file as a module and import fact():

Python
>>> from fact import fact
>>> fact(6)
720

But you can also run it as a standalone by passing an integer argument on the command-line for testing:

Shell
$ python3 fact.py 6
720

If you would like to learn more about running scripts with command line arguments check out this course on Command Line Interfaces in Python.

00:00 In this video, you’ll learn about executing a module as a script. Is a module also a Python script? Well, yeah! Any .py file that contains a module is essentially also a Python script.

00:11 Let me have you take a look at that. If we were to open up the code for mod.py, you can see it’s very simple. And just as a reminder, you set up a string, a list, defined a function called printy(), and a class called Classy.

00:24 What if you were to execute mod.py as a script? Is it possible? Sure. As long as you’re in the same directory, type python or python3 mod.py, and in this case, mod.py doesn’t output anything.

00:37 So, that’s what you should get. No errors. It apparently worked. It’s not very interesting since it’s only defining objects and then it doesn’t really do anything with them. Now, you could modify it.

00:46 You could print(s), print(a), run printy(),

00:57 even define x as a Classy object and then print out x. Okay. So I’m re-saving. It should be a little bit more interesting.

01:06 python3 mod.py. Okay, so it printed the string, printed out the list, showed the argument for printy() and then it shows that when this is running, the name of the module is __main__, and Classy object.

01:20 What does it look like when you import it now? Start the REPL.

01:26 Inside that REPL session, if you were to run import mod, what’s going to happen? It’s going to run all that code. One note you might notice that here, it used to say __main__, now it says mod. And it outputs it.

01:38 Now, this is probably not what you want. You probably want when you run mod.py for it to show the output, but when you import mod, you may not want this output to happen.

01:49 You may want to be able to show output for testing purposes, but you may not want it to happen every time you import it. It would be much better if the output was optional.

02:00 So, there’s something to help out.

02:03 Is there something you can do if you don’t want that module to generate any output when you’re simply importing it? There is a tool that can help with this.

02:11 It uses what’s called a dunder variable. Dunder variables are variables that have double underscores (__) before their names. In this case, the dunder variable is actually __name__.

02:21 __name__ will automatically be set to the name of the module when it’s imported. That’s different from when a Python script, a .py file, is run as a standalone script. In that circumstance, __name__ is set to the string '__main__'. So, how can you use this?

02:42 I’m going to exit here, go back to mod.py, and I’m going to change the code a little bit. Just before all of this starts, create an if statement. And in the if statement you’re going to use that variable, that dunder variable of __name__.

02:57 So if __name__ == '__main__':, which is what happens when you execute the script by itself—not importing—then go ahead and do all this activity. I’ll have you tab all this information over.

03:10 So, only if the __name__ is '__main__'. Save. So this time,

03:18 if you were to run python3 and run mod.py, you can see that running it by itself, the __name__ is __main__.

03:26 And if you were to be inside your REPL, in that case, if you were to import mod, it doesn’t, which is pretty neat! So again, going back to dir(), you might remember that, right? So here is mod imported, right? And you might remember this guy. I don’t know if you noticed him before, but what is the current __name__? Well, what’s running here is this __main__ REPL session.

03:48 If you were to go inside and say, well, what is mod.__name__? Well, mod.__name__ is 'mod'. However, if a file is run as a standalone script, __name__ is going to be set to the string '__main__'.

04:01 And that’s how you can use that test. Pretty neat! One reason that you may want to run the module as a standalone script is to test the contents of it, so that’s what this next example is all about. Make a new file, call it fact.py.

04:22 And inside fact.py, you’re going to define a pretty simple function that is a factorial, and just call it fact() again.

04:44 You can set up the same conditional statement of if the current __name__ is equal to the string '__main__', then you know it’s being executed then as a standalone script.

04:57 Don’t worry too much about the nitty-gritty of the next chunk of code, but you’re importing another module, the sys (system) module, and you’re going to use a tool called argv that allows you to use command line arguments.

05:11 I’ll include a link to an article that tells you a little bit more about running scripts with command line arguments below this video. To be able to do some testing, you’re going to set up another if statement, and here it’s looking for an optional argument that you can add when you execute the code as a script—then it’s going to print the output of the fact() function after converting this argument into an integer from a string.

05:36 Make sure you save fact.py, and to test out if you can import fact(),

05:42 go ahead and start a new REPL session. from fact import fact, so fact() is available and it takes an argument of n. Let’s say, “What’s the factorial of 6?” So, that shows that fact works as a module.

05:55 Now, you could test the code inside of fact as a standalone script also. If you were back here in the terminal and you were to simply type in python3 fact.py and then give it an argument of 6, that conditional if statement is allowing you to run the code underneath it and print out the result right there in the terminal, therefore allowing a level of testing.

06:21 In the next video, you’ll explore reloading a module.

Avatar image for theramstoss

theramstoss on June 14, 2020

How do you set it up so that you don’t have to import sys and append the path every time? Thanks.

Avatar image for theramstoss

theramstoss on June 14, 2020

Figured it out, sorry!

Avatar image for Alexia

Alexia on Aug. 23, 2021

Hi, I just want to make a quick note on a typo I found here:

Unfortunately, now it also generates output when imported as a module:
$ python3 mod.py
Computers are useless. They can only give you answers.
[100, 200, 300]
arg = Good Day Sir!
<__main__.Classy object at 0x10f7a35f8>

Instead of _ main _ is should be _ mod _ if I am not wrong :)

Avatar image for Bartosz Zaczyński

Bartosz Zaczyński RP Team on Aug. 23, 2021

@Alexia You made an interesting observation here. Both outputs are correct, but they depend on how you call the code inside your module.

Specifically, when you run the module directly through the Python interpreter, then the class will be scoped within the __main__ namespace:

$ python mod.py 
<__main__.Classy object at 0x7f5ee53662b0>

Notice the __main__.Classy name.

On the other hand, importing the module elsewhere will also execute the code, but the class will be scoped differently:

$ python -q
>>> import mod
<mod.Classy object at 0x7f83bcccedc0>

The class appears to be defined in the module’s file now. This is intended and has to do with the implicit __name__ variable, which you typically use to detect when a file is imported vs. executed as a script.

Hence, the if __name__ == "__main__" idiom in Python.

Avatar image for Alexia

Alexia on Sept. 2, 2021

Yes sorry I didn’t explained exactly what I meant. I don’t know how to add a screenshot in this comment but I will try to explain it better.

Under the Desciption of this video, after we created the python file:

s = "Computers are useless. They can only give you answers."
a = [100, 200, 300]

def printy(arg):
    print(f'arg = {arg}')

class Classy:
    pass

print(s)
print(a)
printy('Good Day Sir!')
x = Classy()
print(x)

First we run python3 mod.py from Python interpreter and the scope of the class is <__main__.Classy object at 0x10f7a35f8>.

Then we import the module. In this output the class seems again to be scoped <__main__.Classy object at 0x111324748>.

So in both outputs it is __main__.

Avatar image for ori yungrais

ori yungrais on Sept. 20, 2023

Hi, “05:11 I’ll include a link to an article that tells you a little bit more about running scripts with command line arguments below this video.”

Is there a link?

Avatar image for Chris Bailey

Chris Bailey RP Team on Sept. 20, 2023

Hi @ori yungrais,

There is a course Command Line Interfaces in Python – Real Python and it’s companion written tutorial Python Command-Line Arguments. It’s also now at the bottom of the description text for this lesson. Thanks!

Become a Member to join the conversation.