在Python中,在main()中调用参数是一种不好的做法吗

在Python中,在main()中调用参数是一种不好的做法吗,python,main,Python,Main,函数名main()是否应始终为空并在函数本身中调用参数,或者是否可以将它们作为函数的输入,例如main(arg1、arg2、arg3) 我知道这是可行的,但我想知道这是否是糟糕的编程实践。如果这是一个重复的问题,我表示歉意,但我看不出这个问题是专门针对Python回答的 在大多数其他编程语言中,您要么有零个参数,要么有两个参数: int main(char *argv[], int argc) 表示传递给参数的参数。但是,在Python中,可以通过sys模块访问这些内容: import sys

函数名
main()
是否应始终为空并在函数本身中调用参数,或者是否可以将它们作为函数的输入,例如
main(arg1、arg2、arg3)


我知道这是可行的,但我想知道这是否是糟糕的编程实践。如果这是一个重复的问题,我表示歉意,但我看不出这个问题是专门针对Python回答的

在大多数其他编程语言中,您要么有零个参数,要么有两个参数:

int main(char *argv[], int argc)
表示传递给参数的参数。但是,在Python中,可以通过
sys
模块访问这些内容:

import sys

def main():
    print(sys.argv, len(sys.argv))
但是,您可以扩展它,以便将argv和argc传递到python函数中,类似于其他语言是:

import sys

def main(argv, arc):
    print(argv, arc)

if __name__ == '__main__':
    main(sys.argv, len(sys.argv))
但是让我们暂时忘记argv/argc——为什么要将某些内容传递给main。您在main之外创建了一些内容,并希望将其传递给main。这可能发生在两种情况下:

  • 您从其他函数多次调用main
  • 您已经在
    main
    之外创建了要传递的变量
  • 第一点绝对是不好的做法
    main
    应该是唯一的,并且在程序开始时只调用一次。如果需要多次调用,则
    main
    中的代码不属于
    main
    中。把它分开

    第二点看起来似乎有道理,但实际上你是这样做的:

    def main(a, b):
        print(a, b)
    
    if __name__ == '__main__':
        x = 4
        y = 5
        main(x, y)
    

    但是
    x
    y
    不是全局变量吗?好的做法是假设这些属性位于文件的顶部(以及多个其他属性-它们是常量等),并且不需要将它们作为参数传递。

    按照以下模式:

    def main():
        ...stuff...
    
    if __name__ == '__main__':
        main()
    
    它允许您的脚本直接运行,如果使用安装工具进行打包,则在安装包时通过指定main作为入口点自动生成可执行脚本

    见:

    您可以向
    setup.py
    中添加如下内容:

    entry_points={
        'console_scripts': [
            'my_script = my_module:main'
        ]
    }
    
    然后,当你构建一个包时,人们可以在他们的虚拟环境中安装它,并立即在他们的路径上获得一个名为
    my_script
    的脚本

    像这样的自动脚本创建需要一个不带必需参数的函数

    允许您导入脚本并公开其功能是一个好主意,既可以用于代码重用,也可以用于测试。我建议您采用这种模式:

    import argparse
    
    def parse_args():
        parser = argparse.ArgumentParser()
        #
        # ... configure command line arguments ...
        #
        return parser.parse_args()
    
    def do_stuff(args):
        #
        # ... main functionality goes in here ...
        #
    
    def main():
        args = parse_args()
        do_stuff(args)
    
    if __name__ == '__main__':
        main()
    
    这使您可以直接运行脚本,自动生成一个行为与此相同的脚本,还可以导入脚本并调用
    do\u stuff
    重新使用或测试实际功能


    评论中提到了这篇博文:它在main上使用了一个默认参数来允许依赖项注入进行测试,但是,这是一篇非常古老的博文(从那时起,
    getopt
    库已经被取代了两次)我认为这种模式更优越。

    我更愿意看到
    main
    接受参数,而不是直接访问
    sys.argv

    这使得其他Python模块更容易重用主函数

    import sys
    
    def main(arg):
        ...
    
    if __name__ == "__main__":
        main(sys.argv[1])
    
    现在,如果我想将这个模块作为另一个模块的脚本执行,我可以(在我的另一个模块中)编写它


    如果
    main
    使用
    sys.argv
    这就更难了。

    这是一个主要基于观点的问题。但不,这不是坏习惯。不管怎么说,在Python中,名为main的函数没有特殊的状态。我们可以停止以基于意见的方式结束设计问题吗--只需回答“两个选项都不是天生比另一个好”和boom,这是一个有用的问题,有一个有用的答案。
    main()
    只是一个命名约定,不管你在那里做什么,另一方面,
    如果uuuu name_uuu=='\uuuuu main\uuuu':
    块应该是最小的,这样在导入module@Aran-Fey完全同意,在Python中,即使答案不清楚,最佳实践问题也可以,但显然不是每个人都这么认为,请看@Chris_Rands,是的,这是一种令人悲伤的状况。Python风格/设计IMO是学习该语言的重要组成部分,即使它在技术上是自以为是的。Python代码被设计为可读的,而不是编译的,永远被遗忘的。你的第二个代码片段是我放在
    sys.argv[1]
    sys.argv[2]
    的地方,而不是
    x
    a d
    y
    我不喜欢你的第一个代码片段,因为导入模块时
    sys.argv
    是空的,我认为
    main()
    是指它可以在执行模块时调用,也可以在imported@Chris_Rands啊。我明白你的意思。让我来编辑这样的自动脚本创建需要一个不带参数的函数…不完全是这样。您可以使用def main(argv=None):这有什么意义?从自动生成的脚本调用argv时,不会传递argv。但是,是的,这应该是一个*需要*不需要参数的函数。我见过这样的模式,测试可以显式地传入argv列表,而不需要对sys.argv的内容进行monkeypatch。对我来说,这似乎是一个合理的方法。Guido在他的博客上推荐了这一方法:好的,依赖注入似乎是一个合理的方法,尽管我个人可能只是制作主构造参数并将其传递给其他对象,然后测试该函数,因此,您没有改变被测行为的条件。其他模块不应直接使用
    main
    。在解析完任何参数后,它们应该使用
    main
    委托给的相同库代码。开发人员应该努力将API与CLI分离。
    from main_script import main
    
    main("use this argument")