每个程序员在学习编程的过程中, 肯定没少写过 main()函数, Python 程序员也不例外. 本文为大家分享 Python 之父 Guido van Rossum 推荐的函数写法, 可以大大提高这个函数的灵活性.
一般来说, Python 程序员可能是这样写 main()函数的:
- """Module docstring.
- This serves as a long usage message.
- """
- import sys
- import getopt
- def main():
- parse command line options
- try:
- opts, args = getopt.getopt(sys.argv[1:], "h", ["help"])
- except getopt.error, msg:
- print msg
- print "for help use --help"
- sys.exit(2)
- # process options
- for o, a in opts:
- if o in ("-h", "--help"):
- print __doc__
- sys.exit(0)
- # process arguments
- for arg in args:
- process(arg) # process() is defined elsewhere
- if name == "main":
- main()
Guido 也承认之前自己写的 main()函数也是类似的结构, 但是这样写的灵活性还不够高, 尤其是需要解析复杂的命令行选项时. 为此, 他向大家提出了几点建议.
添加可选的 argv 参数
首先, 修改 main()函数, 使其接受一个可选参数 argv, 支持在交互式 shell 中调用该函数:
- def main(argv=None):
- if argv is None:
- argv = sys.argv
- etc., replacing sys.argv with argv in the getopt() call.
这样做, 我们就可以动态地提供 argv 的值, 这比下面这样写更加的灵活:
def main(argv=sys.argv):
etc.
这是因为在调用函数时, sys.argv 的值可能会发生变化; 可选参数的默认值都是在定义 main()函数时, 就已经计算好的.
但是现在 sys.exit()函数调用会产生问题: 当 main()函数调用 sys.exit()时, 交互式解释器就会推出! 解决办法是让 main()函数的返回值指示退出状态(exit status). 因此, 最后面的那行代码就变成了这样:
- if name == "main":
- sys.exit(main())
并且, main()函数中的 sys.exit(n)调用全部变成 return n.
定义一个 Usage()异常
另一个改进之处, 就是定义一个 Usage()异常, 可以在 main()函数最后的 except 子句捕捉该异常:
- import sys
- import getopt
- class Usage(Exception):
- def init(self, msg):
- self.msg = msg
- def main(argv=None):
- if argv is None:
- argv = sys.argv
- try:
- try:
- opts, args = getopt.getopt(argv[1:], "h", ["help"])
- except getopt.error, msg:
- raise Usage(msg)
- more code, unchanged
- except Usage, err:
- print>>sys.stderr, err.msg
- print>>sys.stderr, "for help use --help"
- return 2
- if name == "main":
- sys.exit(main())
这样 main()函数就只有一个退出点 (exit) 了, 这比之前两个退出点的做法要好. 而且, 参数解析重构起来也更容易: AxiTrader 返佣 www.kaifx.cn/broker/axitrader.html, 在辅助函数中引发 Usage 的问题不大, 但是使用 return 2 却要求仔细处理返回值传递的问题.
python 中 name == 'main' 的作用
经典的英文解释: Make a script both importable and executable
中文解释: 使脚本可以被调用 import 并且也可以直接运行
1, 直接运行
cat test_fun.py
- def fun():
- print(name)
- print('this is fun')
- if name == 'main':
- fun()
- print('this is main')
python test_fun.py
- main
- this is fun
- this is main
2, 被调用 import
- import test_fun
- test_fun.fun()
- test_fun
- this is fun
调用导入时: 此处输出没有显示 "main", 也就是说模块 name = 'main' 下面的代码并未执行, main 函数没有执行.
这个功能还有一个用处: 调试代码的时候, 在 "if name =='main'" 中加入一些我们的调试代码, 我们可以让外部模块调用的时候不执行我们的调试代码, 但是如果我们想排查问题的时候, 直接执行该模块文件, 调试代码能够正常运行!
?python 是一种解释型脚本语言, 和 C/C++ 语言不同, C/C++ 程序从 main 函数开始执行, python 程序从开始到结尾顺序执行. 先总结下 python 中的 main 函数的作用: 让模块 (函数) 可以自己单独执行(调试), 相当于构造了调用其它函数的入口, 这就类似于 C/C++ 里面的 mian 函数了.
一方面: 我们想要自己单独执行(调试)
这里我们实际调试一下(假设这个文件是 test.py):
- #test.py
- print('Hello World!')
- def aaa():
- print('this message is from aaa function')
- def main():
- print('this message is from main function')
- if name == 'main':
- main()
- print ('now name is %s' %name)
执行 python test.py?? 输出:
- Hello World!
- this message is from main function
- now name is main
这里我们看到我们定义的 aaa 函数没有被执行, 而 main 函数里面的内容被执行了, 表明? if name == 'main':? 这条判断语句是通过的, 执行了判断条件里的 main();?
另一方面: 通过 import 命令就可以使用其它. py 文件里面的函数, 我们将 test.py 中的模块 (函数) 导入 call.py, 需注意 test.py 和 call.py 放在同一个文件夹下;
- #call.py
- from test import aaa
- aaa()
- print ('now name is %s' %name)
执行 python? call.py? 输出:
- Hello World!
- this message is from aaa function
- now name is main
所以当我们自己写了. py 文件, 想要测试里面的函数时, 就这样构造一个 main 函数入口就可以调用测试自己写的函数啦~
来源: http://www.bubuko.com/infodetail-3194733.html