在Python中,如何在另一个py文件的[if __name__ =='__main__']内部调用子例程?

时间:2018-07-27 03:43:16

标签: python main python-module

假设我在python控制台中,并且希望在同一过程中启动另一个python程序。 python程序如下所示:

StackPanel

并且我不允许对其进行修改。

执行此操作的正确方法是什么?我可以使用其他参数列表(例如C ++或Java)将其称为“主函数”吗?

我不反对方法被认为是黑客。 Python是一种高度可扩展的解释语言,我将尽一切必要绕过此限制

2 个答案:

答案 0 :(得分:2)

您可以读取文件并使用exec来使用当前全局变量执行代码,以便__name__ == '__main__'为真。

exec(open('file.py').read(), globals())

答案 1 :(得分:2)

您不能“调用其主要功能”,因为它没有一个。

实际上,处理此问题的通常方法是将所有这些代码移入一个函数,然后使__main__保护代码仅调用该代码即可。

def main(args):
    for key in args:
        print(key)

if __name__ == '__main__':
    main(sys.argv)

然后您可以调用其主函数,并向其传递所需的任何args。

但是,如果您无法修复文件,那将无法正常工作。


那么,您可以做什么 ?这完全取决于您需要如何遵循通常的python another.py语义。


快速而肮脏的方法是按照blhsing's answer的建议进行操作:读取文件,然后通过您自己的脚本中的execglobals

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