Jithin Johnson
Jithin Johnson

Reputation: 372

How to execute if __name__ != "__main__"?

I have a code which I cannot alter named temp.py which contains

if __name__ == "__main__":
   *some pieces of code not a function call*

I want to import temp into an other file which I can edit but importing doesnot run the above part. I know I can use subprocess to run temp.py but that is not what I want. I want to import the module entirely but cannot alter the code. I have heard of a module called imp but is depreceated now.

EDIT:

I am aware that code under the if statement is not meant to be excecuted when imported, but lets just assume temp.py is written in a really worse way and I cannot alter it.

Upvotes: 2

Views: 2978

Answers (3)

Almog-at-Nailo
Almog-at-Nailo

Reputation: 1182

something like this is really bad practice but will work:

file1.py has the "main" part:

def foo1():
    print("foo1")


if __name__ == '__main__':
    print("main function started")
    foo1()
    print("main function finished")

file2.py is an intermediary file:

from file1 import *
with open('file1.py') as f:
    lines = f.readlines()

a = "if __name__ == '__main__':\n"
new_main = ["def main():\n"] + lines[lines.index(a)+1:]
exec("".join(new_main))

file3.py used to import file2 as if it is the file1 module:

import file2

file2.main()
file2.foo1()

output when running file3.py:

main function started
foo1
main function finished
foo1

Upvotes: 1

juanpa.arrivillaga
juanpa.arrivillaga

Reputation: 95873

You are trying to go against the import system. Pretty much any thing you end up doing to achieve this will be a hack.

Consider we have a file:

(py39) Juans-MacBook-Pro:~ juan$ cat subvert.py
def foo(x):
    print("Hello, ", x)


if __name__ == "__main__":
    foo("Goodbye")

Note, if I open up a REPL, I'm in __main__, so at your top-level script, you could just do:

(py39) Juans-MacBook-Pro:~ juan$ python
Python 3.9.5 (default, May 18 2021, 12:31:01)
[Clang 10.0.0 ] :: Anaconda, Inc. on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> __name__
'__main__'
>>> exec(open("subvert.py").read())
Hello,  Goodbye

Of course, just execing the source code directly in the same namespace is probably not what you want...

Note, we can pass our own namespace:

>>> namespace = {"__name__": "__main__"}
>>> exec(open("subvert.py").read(), namespace)
Hello,  Goodbye

So our module's namespace won't be clobbered.

Now, if you want an actual module after it, you could hack together something like:

>>> import types
>>> module = types.ModuleType("__main__")
>>> module
<module '__main__'>
>>> exec(open("subvert.py").read(), module.__dict__)
Hello,  Goodbye
>>> module.foo('bar')
Hello,  bar

I wouldn't expect any of this to work well. It won't have all the attributes of a fully loaded module, look at importlib if you find you need to flesh it out more.

Upvotes: 2

alirezaarzehgar
alirezaarzehgar

Reputation: 299

Python programmers use following mechanism for avoiding importing a main script on another scripts.

if __name__ == "__main__":
    # TODO

Read its philosophia here.

When some code used if __name__ == "__main__": means to you shouldn't import its code and this work isn't true.

But you can use this mechanism :

def main():
    # TODO

if __name__ == "__main__":
    main()

In this case everyone can import your main script and use main function.

Upvotes: -1

Related Questions