【问题标题】:Python: How to Call Module from Other Path With __name__ == '__main__'Python:如何使用 __name__ == '__main__' 从其他路径调用模块
【发布时间】:2018-09-08 23:54:45
【问题描述】:

正如这个答案how to import module 中所述,可以通过这种方式导入位于另一条路径中的模块:

import sys
sys.path.append('PathToModule')
import models.user

我的问题是:

如果以这种方式设置此其他模块,我如何执行此其他模块(并向其传递参数):

if __name__ == '__main__':
    do_something()

do_something() 使用argparse.ArgumentParser 来处理提供的参数?

在出现第一个问题/评论后,我添加了以下内容

我可以通过

传递参数
sys.argv[1:] = [
    "--param1", "123",
    "--param2", "456",
    "--param3", "111"
]

所以这个话题已经涵盖了。

为什么要调用另一个带参数的模块?

我希望能够为另一个项目做一些小的回归测试。我想通过git clone 获得这个其他项目,并在本地提供不同的版本,如果需要,我也可以调试。

但我不想过多地参与其他项目(因此分叉没有意义)。

所以我剩下的问题是

调用其他模块时如何调整__name__ 的内容?

【问题讨论】:

  • 大概你可以写在argparse位周围。它到底在做什么?
  • 一个设计精美的模块(旨在以这种方式使用)会将内容解析为一组参数以传递给 do_something 函数,在这种情况下,您只需调用 module.do_something正确的论点。
  • 如果该模块不打算以这种方式使用,那么正确的答案可能是将其作为subprocess 启动。
  • 如果它打算以这种方式工作,但设计得不是很仔细,你通常可以以某种方式伪造 argparse(如果最坏的情况变得更糟,黑客设置 sys.argv 或猴子补丁模块)或复制/粘贴顶级脚本代码所做的相同工作(但简化为仅处理您的情况)。丑陋,但解决方法是改进其他模块。
  • 所以我的问题是:当__name__ 的内容被提供给我想调用的模块时,我该如何调整它

标签: python


【解决方案1】:

有多种方法可以解决这个问题。

  1. 如果你要导入的模块写得很好,它应该有单独的函数来解析命令行参数和实际工作。它应该看起来像这样:

    def main(arg1, arg2):
        pass  # do something
    
    def parse_args():
        parser = argparse.ArgumentParser()
        ... # lots of code
        return vars(parser.parse_args())
    
    if __name__ == '__main__':
        args = parse_args()
        main(**args)
    

    在这种情况下,您只需导入模块,然后使用正确的参数调用其main 函数:

    import yourModule
    yourModule.main('foo', 'bar')
    

    这是最优解。

  2. 如果模块没有定义这样的main函数,可以手动设置sys.argv,使用runpy.run_module执行模块:

    import runpy
    import sys
    
    sys.argv[1:] = ['foo', 'bar']
    runpy.run_module('yourModule', run_name='__main__', alter_sys=True)
    

    注意,这只是执行模块;它不会导入它。 (即模块不会被添加到 sys.modules 并且您不会获得可以与之交互的模块对象。)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-05-12
    • 2016-04-22
    • 2014-12-15
    • 1970-01-01
    • 1970-01-01
    • 2019-11-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多