在 Python 中,如何调用另一个 py 文件的 [if __name__ == '__main__'] 中的子程序?
In Python, how to invoke subroutine inside [if __name__ == '__main__'] of another py file?
假设我在 python 控制台中并想在同一进程中启动另一个 python 程序。 python 程序如下所示:
import sys
if __name__ == '__main__':
args = sys.argv
for key in args:
print(key)
而且不允许修改。
这样做的正确方法是什么?我可以用不同的参数列表(如 C++ 或 Java 调用它 'main function' 吗?
我不反对被认为是黑客攻击的方法。 Python 是一种高度可扩展的解释性语言,我将尽一切努力绕过此限制
您可以读取该文件并使用 exec
来执行带有当前全局变量的代码,这样 __name__ == '__main__'
就会成立。
exec(open('file.py').read(), globals())
你不能"call its main function",因为它没有。
事实上,处理这个问题的通常方法是将所有这些代码移动到一个函数中,然后让 __main__
保护代码调用它:
def main(args):
for key in args:
print(key)
if __name__ == '__main__':
main(sys.argv)
然后你可以调用它的主函数,传递你想要的任何参数。
但如果您不能修复文件,那将不起作用。
那么,您可以做什么?这完全取决于您需要如何准确地遵循通常的 python another.py
语义。
快速而简单的方法是根据您自己的脚本执行 suggests: read the file, and exec
it with the globals 的操作:
with open('another.py') as f:
exec(f.read(), globals())
请注意,这将使 sys.argv
保持不变。当然,您可以先手动将其设置为其他值:
_argv = sys.argv
sys.argv = ['args', 'i', 'want', 'it', 'to', 'see']
try:
with open('another.py') as f:
exec(f.read(), globals())
finally:
sys.argv = _argv
如果您是从另一个模块而不是您的顶级脚本执行此操作,那将不起作用,但稍作修改后,它将:
with open('another.py') as f:
exec(f.read(), sys.modules['__main__'].__dict__)
但是您最好创建一个干净的全局命名空间。该脚本可能不希望让您的全局变量随处可见——并且它可能会更改您不希望它更改的内容。这同样简单:
with open('another.py') as f:
exec(f.read(), {})
(请注意,这仍将自动继承您通常需要的当前 builtins
。如果您出于某种原因 不想 ,请参阅 exec
文档。)
如果您想保证执行它的方式与 运行正常运行脚本的方式完全相同,请使用 runpy
模块。
当你运行python -m another
时,它最终做的是:
runpy.run_module(sys.argv[0], run_name="__main__", alter_sys=True)
因此,您可以手动执行相同的操作:
runpy.run_module('another', run_name='__main__')
是否要添加 alter_sys=True
取决于您的目的。如果没有它,如果脚本尝试访问 sys.argv
(就像您的脚本所做的那样)或 sys.modules['__main__']
,它将看到您的值,而不是它自己的值。
如果你想模拟 python another.py
,你会想使用 importlib
创建完整的 __spec__
和相关对象,然后调用 runpy.run_path
.
假设我在 python 控制台中并想在同一进程中启动另一个 python 程序。 python 程序如下所示:
import sys
if __name__ == '__main__':
args = sys.argv
for key in args:
print(key)
而且不允许修改。
这样做的正确方法是什么?我可以用不同的参数列表(如 C++ 或 Java 调用它 'main function' 吗?
我不反对被认为是黑客攻击的方法。 Python 是一种高度可扩展的解释性语言,我将尽一切努力绕过此限制
您可以读取该文件并使用 exec
来执行带有当前全局变量的代码,这样 __name__ == '__main__'
就会成立。
exec(open('file.py').read(), globals())
你不能"call its main function",因为它没有。
事实上,处理这个问题的通常方法是将所有这些代码移动到一个函数中,然后让 __main__
保护代码调用它:
def main(args):
for key in args:
print(key)
if __name__ == '__main__':
main(sys.argv)
然后你可以调用它的主函数,传递你想要的任何参数。
但如果您不能修复文件,那将不起作用。
那么,您可以做什么?这完全取决于您需要如何准确地遵循通常的 python another.py
语义。
快速而简单的方法是根据您自己的脚本执行 exec
it with the globals 的操作:
with open('another.py') as f:
exec(f.read(), globals())
请注意,这将使 sys.argv
保持不变。当然,您可以先手动将其设置为其他值:
_argv = sys.argv
sys.argv = ['args', 'i', 'want', 'it', 'to', 'see']
try:
with open('another.py') as f:
exec(f.read(), globals())
finally:
sys.argv = _argv
如果您是从另一个模块而不是您的顶级脚本执行此操作,那将不起作用,但稍作修改后,它将:
with open('another.py') as f:
exec(f.read(), sys.modules['__main__'].__dict__)
但是您最好创建一个干净的全局命名空间。该脚本可能不希望让您的全局变量随处可见——并且它可能会更改您不希望它更改的内容。这同样简单:
with open('another.py') as f:
exec(f.read(), {})
(请注意,这仍将自动继承您通常需要的当前 builtins
。如果您出于某种原因 不想 ,请参阅 exec
文档。)
如果您想保证执行它的方式与 运行正常运行脚本的方式完全相同,请使用 runpy
模块。
当你运行python -m another
时,它最终做的是:
runpy.run_module(sys.argv[0], run_name="__main__", alter_sys=True)
因此,您可以手动执行相同的操作:
runpy.run_module('another', run_name='__main__')
是否要添加 alter_sys=True
取决于您的目的。如果没有它,如果脚本尝试访问 sys.argv
(就像您的脚本所做的那样)或 sys.modules['__main__']
,它将看到您的值,而不是它自己的值。
如果你想模拟 python another.py
,你会想使用 importlib
创建完整的 __spec__
和相关对象,然后调用 runpy.run_path
.