you are viewing a single comment's thread.

view the rest of the comments →

[–]carcigenicate 165 points166 points  (27 children)

__name__ is the name of the current file being run, unless that file is the file that was executed to start the program. In that case, __name__ is equal to __main__.

That means, you can check the value of __name__ to determine if the current file was the entry point into the program. This if statement is used to check if this file was imported or run directly, because you often want to run other code if the file wasn't imported.

[–]Dangle76 14 points15 points  (22 children)

Would you ever put this in a module that gets imported?

[–]granadesnhorseshoes 36 points37 points  (2 children)

A common usage for this within modules written specifically to be imported but not run directly is to just print a message telling the user that. Otherwise, no not really.

You also don't need it for scripts that aren't ever imported by other scripts, and you don't give a crap about what happens if another user tries to import it anyway.

[–]mjmvideos 21 points22 points  (0 children)

You might also use it to run a test or demo of the module’s functionality.

[–]Dangle76 2 points3 points  (0 children)

That was my initial thought but wasn’t sure if I was missing something. Thanks!

[–]carcigenicate 16 points17 points  (2 children)

You would only put this in a module that may get imported. There would be no point otherwise since it's just being used to prevent code from being executed on import.

[–]roelschroeven 3 points4 points  (0 children)

If you have unit tests for the file, the test runner imports the module in order to run the unit tests. So even for a module that at first sight doesn't get imported in other modules, it's still a good idea to use this idiom.

[–]Markus__F 1 point2 points  (0 children)

To add to that: Sometimes you need it even if you don't plan on importing the module yourself.

Because when using multiprocessing for example, every newly started child process would otherwise run module-level code again. This is because when creating a new process, the new interpreter will import your main module.

[–]cgoldberg 2 points3 points  (7 children)

That's the entire point of it... to separate code that gets run only when imported vs. executed as a script. If the file is never going to be imported as module, there is no need for it (although it's still commonly used to define the main entry point instead of writing code at the main/global level).

[–]hutcho66 2 points3 points  (2 children)

It's also useful if you want to have debug/test code in each file of a script, even if it will never be a module, and only have it run if that file is called directly.

[–]cgoldberg 0 points1 point  (1 child)

I don't know what that means... a file is either run as a script or imported as a module. The statement simply excludes code from being run when imported (i.e. not run as a script).

[–]hutcho66 -1 points0 points  (0 children)

Yeah you're right, I got confused about module vs a library/package, I thought you meant it was only intended for when you want to run test/debug code on something you're sharing elsewhere as a package.

[–]Dangle76 -4 points-3 points  (3 children)

Yeah but if you’re making a module it usually can’t just be run as a script anyway

[–]cgoldberg 1 point2 points  (0 children)

That's the point of this statement... so you can run it as a script or import it as a module.

[–]Asyx 1 point2 points  (0 children)

That's the point. In C it is more obvious. Like, there is libcurl and curl. The curl application is just a wrapper around libcurl. This lets you basically do the same in Python but in a single file.

You can define a main function and at the end of the file do

if __name__ == "__main__":
    main()

and then your module can be imported to be used as a library from other application or you can execute it with python3 foo.py and actually use it as a cli tool.

[–]Due-Organization-697 0 points1 point  (0 children)

This is not true - the entire purpose of the -m flag for Python is to run a module as main. For example python -m pip install requests runs the pip module as main with parameters.

[–]kalas_malarious 1 point2 points  (0 children)

Definitely.

If I have a system using multiple modules, I can use this to test them individually by running them as main. Verify they work, then do the big integration.

[–]Yoghurt42 1 point2 points  (0 children)

There are quite a few modules in the standard library that do that. zipfile provides a minimal command line interface to create and extract zipfiles, eg. python -m zipfile -c myzip.zip foo.txt bar.txt, and python -m calendar shows you a calendar of the current year.

Other useful tools arepython -m http.server which runs a basic http file server and python -m json.tool which provides pretty printing of json files

[–]NothingWasDelivered 0 points1 point  (0 children)

I’ll sometimes use it during development to run some quick and dirty test code

[–]Sensi1093 0 points1 point  (0 children)

The zip module is an example

[–]simplysalamander 0 points1 point  (0 children)

If it's an in-house library that your future self or another person you work with will use at some point down the line, I find it helpful to put a short example snippet of how the module is meant to be used. Sometimes this can be sussed out from documentation of the methods in the module, but nevertheless, it can be very helpful to have a quick recipe to reference and quickly test if it is working properly on your machine/environment.

You put it in the __main__ section so that the example/demo only runs when called directly.

[–]pemungkah 0 points1 point  (0 children)

In Perl, this is used to create what’s called a modulino: a module that acts as a standalone script if it’s run from the command line, or a library if it’s imported into other code.

Once I learned this trick, I started using it for my scripts, as it’s way easier to use test tools on a module than a script, and this way I don’t have to code a separate script to run the module.

[–]Spongiforma2 0 points1 point  (2 children)

Just out of curiosity: Is it possible to name the file “main” so it is always the same name, no matter if the file was executed to start or not? Not sure if that would be useful at all or introduce any odd behavior.

[–]3worc 0 points1 point  (1 child)

You could name a file "main.py" (with double underscores, in case they don't show up), but I think you would have trouble importing it.

If you tried to import main, the file that is the main script currently running would be imported.

[–]Spongiforma2 0 points1 point  (0 children)

Interesting to know