在 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.