Reputation: 372
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
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
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
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