2

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.

Jithin Johnson
  • 352
  • 1
  • 10
  • 1
    If a script is being used as a module then the caller defines what exactly it needs to run. – NotAName Aug 26 '21 at 07:11
  • 2
    If the original author of temp.py enclosed that piece of code in 'if __name__ == "__main__":', then it probably was not meant to be imported into another script. If you need to import it, it's best to refactor that piece of code into a function. – CoffeeSyntax Aug 26 '21 at 07:14
  • 2
    Do you want to import your temp script that contain main on another scripts with main ? Why ? This is wrong. Programmers uses `if __name__ == "__main__":` mechanism for avoid this. – alirezaarzehgar Aug 26 '21 at 07:14
  • Why can't you alter the code? – juanpa.arrivillaga Aug 26 '21 at 07:14
  • Yes I clearly know how the __name__== "__main__" works but it is written in an orthodox manner. Most of the code is written under the broiler plate. I can't change it because I need to submit it back to the cloud. – Jithin Johnson Aug 26 '21 at 07:18
  • If you can't alter it and can't run it as a sub-process then you're basically out of luck. Copy-paste and manage your own version of the code in question I guess? – apokryfos Aug 26 '21 at 07:23
  • There's no way to do this with `import`. Maybe just `exec` the source code string? – juanpa.arrivillaga Aug 26 '21 at 07:32
  • @juanpa.arrivillaga could you please explain more? – Jithin Johnson Aug 26 '21 at 07:34
  • 2
    what if instead of importing `temp.py`, you create another file `temp2.py` which imports `temp.py`, reads the main function and exports it as a function? like literally use `open()` to read `temp.py` and parse out everything after the `if __name__ == "__main__":` part, and export it as a `main()` function? It's really bad practice but it's something – Almog-at-Nailo Aug 26 '21 at 07:42
  • Yeah I was thinking the same. Not the best but still works!! Thanks! – Jithin Johnson Aug 26 '21 at 07:43
  • I tested it out and it seems to work, I posted an answer for anyone else who might want this – Almog-at-Nailo Aug 26 '21 at 08:00
  • @JithinJohnson fine I added an example. – juanpa.arrivillaga Aug 26 '21 at 08:02

3 Answers3

2

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.

juanpa.arrivillaga
  • 88,713
  • 10
  • 131
  • 172
1

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
Almog-at-Nailo
  • 1,152
  • 1
  • 4
  • 20
-1

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.

alirezaarzehgar
  • 171
  • 1
  • 8