在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
中。把它分开
第二点看起来似乎有道理,但实际上你是这样做的:
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 dy
我不喜欢你的第一个代码片段,因为导入模块时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")