Why is Python running my module when I import it, and how do I stop it?
Asked Answered
P

12

279

I have a Python program I'm building that can be run in either of 2 ways: the first is to call python main.py which prompts the user for input in a friendly manner and then runs the user input through the program. The other way is to call python batch.py -file- which will pass over all the friendly input gathering and run an entire file's worth of input through the program in a single go.

The problem is that when I run batch.py, it imports some variables/methods/etc from main.py, and when it runs this code:

import main

at the first line of the program, it immediately errors because it tries to run the code in main.py.

How can I stop Python from running the code contained in the main module which I'm importing?

Protege answered 29/6, 2011 at 16:11 Comment(1)
R
369

Because this is just how Python works - keywords such as class and def are not declarations. Instead, they are real live statements which are executed. If they were not executed your module would be empty.

The idiomatic approach is:

# stuff to run always here such as class/def
def main():
    pass

if __name__ == "__main__":
   # stuff only to run when not called via 'import' here
   main()

It does require source control over the module being imported, however.

Rolfston answered 29/6, 2011 at 16:15 Comment(3)
just to confirm, your comment "stuff only to run when not called via 'import' here" implies the commands to be written under main(), right? Or it doesn't matter??Charioteer
@Goldname The code inside the if statement won't be run when imported, but the main function in itself is defined and ready for use even through an import. This module would just execute the main function when run, and not execute it if imported. It all depends on what you want to do. If you don't need the commands inside main elsewhere, by all means write them inside the if. But to me it looks neater.Ectype
@Ectype I would argue that it's better practice to always define a main so that any names defined inside it don't end up in the global namespace, which can cause weird bugs, like if you have a function that accesses a free variable by mistake, and there's a global with the same name.Plenary
D
87

Due to the way Python works, it is necessary for it to run your modules when it imports them.

To prevent code in the module from being executed when imported, but only when run directly, you can guard it with this if:

if __name__ == "__main__":
    # this won't be run when imported

You may want to put this code in a main() method, so that you can either execute the file directly, or import the module and call the main(). For example, assume this is in the file foo.py.

def main():
    print "Hello World"

if __name__ == "__main__":
    main()

This program can be run either by going python foo.py, or from another Python script:

import foo

...

foo.main()
Drummer answered 29/6, 2011 at 16:16 Comment(0)
A
21

Use the if __name__ == '__main__' idiom -- __name__ is a special variable whose value is '__main__' if the module is being run as a script, and the module name if it's imported. So you'd do something like

# imports
# class/function definitions
if __name__ == '__main__':
    # code here will only run when you invoke 'python main.py'
Analects answered 29/6, 2011 at 16:15 Comment(0)
A
6

Unfortunately, you don't. That is part of how the import syntax works and it is important that it does so -- remember def is actually something executed, if Python did not execute the import, you'd be, well, stuck without functions.

Since you probably have access to the file, though, you might be able to look and see what causes the error. It might be possible to modify your environment to prevent the error from happening.

Anfractuosity answered 29/6, 2011 at 16:14 Comment(3)
As a note: if there is no way to modify the environment so that the error can be prevented, maybe you should use a different moduleAnfractuosity
I just want to be sure based on your answer. Am I write? when we are importing, the interpreter sees the def and assigns the body of function to the name of the function, but it does not execute it. Is this true?Removable
@GreenFalcon Yes. def foo(): doSomthingWakciy() won't break until you call foo()Anfractuosity
R
5

Put the code inside a function and it won't run until you call the function. You should have a main function in your main.py. with the statement:

if __name__ == '__main__':
  main()

Then, if you call python main.py the main() function will run. If you import main.py, it will not. Also, you should probably rename main.py to something else for clarity's sake.

Rowen answered 11/3, 2014 at 15:45 Comment(0)
M
4

There was a Python enhancement proposal PEP 299 which aimed to replace if __name__ == '__main__': idiom with def __main__:, but it was rejected. It's still a good read to know what to keep in mind when using if __name__ = '__main__':.

Meistersinger answered 25/3, 2015 at 16:31 Comment(0)
S
3

You may write your "main.py" like this:

#!/usr/bin/env python

__all__=["somevar", "do_something"]

somevar=""

def do_something():
    pass #blahblah

if __name__=="__main__":
    do_something()
Submultiple answered 29/6, 2011 at 16:15 Comment(0)
A
3

I did a simple test:

#test.py

x = 1
print("1, has it been executed?")


def t1():
     print("hello")
     print("2, has it been executed?")


def t2():
     print("world")
     print("3, has it been executed?")


def main():
     print("Hello World")
     print("4, has it been executed?")


print("5, has it been executed?")
print(x)

# while True:
# t2()

if x == 1:
     print("6, has it been executed?")

#test2.py

import test

When executing or running test2.py, the running result:

1, has it been executed?

5, has it been executed?

1

6, has it been executed?

Conclusion: When the imported module does not add if __name__=="__main__":, the current module is run, The code in the imported module that is not in the function is executed sequentially, and the code in the function is not executed when it is not called.

in addition:

def main():
    # Put all your code you need to execute directly when this script run directly.
    pass

if __name__ == '__main__':
    main() 
else:
    # Put functions you need to be executed only whenever imported
Ankara answered 7/1, 2022 at 13:40 Comment(0)
R
0

A minor error that could happen (at least it happened to me), especially when distributing python scripts/functions that carry out a complete analysis, was to call the function directly at the end of the function .py file. The only things a user needed to modify were the input files and parameters. Doing so when you import you'll get the function running immediately. For proper behavior, you simply need to remove the inside call to the function and reserve it for the real calling file/function/portion of code

Reproval answered 14/2, 2022 at 12:3 Comment(0)
L
0

Another option is to use a binary environment variable, e.g. lets call it 'run_code'. If run_code = 0 (False) structure main.py to bypass the code (but the temporarily bypassed function will still be imported as a module). Later when you are ready to use the imported function (now a module) set the environment variable run_code = 1 (True). Use the os.environ command to set and retrieve the binary variable, but be sure to convert it to an integer when retrieving (or restructure the if statement to read a string value),

in main.py:

import os

#set environment variable to 0 (False):
os.environ['run_code'] = '0'


def binary_module():
    #retrieve environment variable, convert to integer
    run_code_val = int(os.environ['run_code'] )
    
    if run_code_val  == 0:
        print('nope. not doing it.')
    if run_code_val == 1:
        print('executing code...')
        # [do something]

...in whatever script is loading main.py:

import os,main

main.binary_module() 

OUTPUT: nope. not doing it.

# now flip the on switch!
os.environ['run_code'] = '1'
main.binary_module()

OUTPUT: executing code...

*Note: The above code presumes main.py and whatever script imports it exist in the same directory.

Legislation answered 20/12, 2022 at 1:25 Comment(0)
W
-2

Although you cannot use import without running the code; there is quite a swift way in which you can input your variables; by using numpy.savez, which stores variables as numpy arrays in a .npz file. Afterwards you can load the variables using numpy.load.

See a full description in the scipy documentation

Please note this is only the case for variables and arrays of variable, and not for methods, etc.

Williford answered 17/6, 2014 at 6:11 Comment(0)
E
-5

Try just importing the functions needed from main.py? So,

from main import SomeFunction

It could be that you've named a function in batch.py the same as one in main.py, and when you import main.py the program runs the main.py function instead of the batch.py function; doing the above should fix that. I hope.

Epigenesis answered 29/6, 2011 at 16:16 Comment(2)
At least on Windows, it doesn't.Voidance
import main does NOT import everything from main into the current namespace. It only adds a single main symbol in the current namespace, so collisions cannot happen.Landmark

© 2022 - 2024 — McMap. All rights reserved.