当前位置: 首页 > 科技观察

写Python脚本的时候一定要加上这个

时间:2023-03-15 13:18:03 科技观察

我发现很多朋友写Python脚本很随意,要么没有函数,要么到处定义函数。反正第一眼看不出来要执行的第一行代码在哪里。此类脚本可读性差,容易隐藏bug。解决这个问题很简单。我们在写Python脚本的时候,一定要加上:defmain():#dosomethingprint("dosomething.")if__name__=="__main__":main()你可能会反对:我想写就写,凭什么听你的并写更多if__name__...?别着急,我说三个理由。首先,它使Python文件的作用更加明确。首先,您需要了解__name__的作用。当脚本被Python解释器直接执行时,它的值为“__main__”。当它被其他Python程序导入时,它的值就是对应的Python脚本的文件名,可以被Python解释器验证。假设有一个some_script.py,其内容如下:print("some_script.py")print(__name__)在Python解释器中导入:?vimsome_script.py?pythonPython3。8.5(v3.8.5:580fbb018f,Jul202020,12:11:27)[Clang6.0(clang-600.0.57)]ondarwinType"help","copyright","credits"or"license"fororeinformation.>>>importsome_scriptsome_script.pysome_script>>>可以看到__name__的值是Python脚本some_script的文件名。也就是说如果__name__=="__main__":导入时下面的代码不会运行。明白这一点,if__name__=="__main__":可以作为区分脚本和库的标志。当我们看到if__name__=="__main__":时,我们认为这是一个可以直接运行的脚本。当你没有看到这行代码时,你会认为它是一个可以被其他程序引用的库。显式优于隐式。不是吗?再举个例子:如果你写了一个库,没有if__name__=="__main__":脚本,叫做bad_script.py,内容如下:defuseful_function(x):returnx*xclassUsefulClass:def__init__(self,x):self.x=x#你自己测试了一下,没有问题foriinrange(7):print(useful_function(i))')if__name__=='__main__':main()runsandprintsUnexpectedcontent,见下图红色部分:查了半天原因,发现是你的脚本输出,你以为别人会骂你?如果你在你的脚本中定义了一个全局变量,如果别人在不合适的位置导入*,你的全局变量也会被导入,造成变量覆盖,很容易出现bug。其次,它使Python文件更具可读性和IDE友好性。if__name__=="__main__":相当于Python程序也有一个入口函数,所有的变量都是从这里定义和使用的,我们可以清楚的知道程序的逻辑从哪里开始(当然需要有意识的把逻辑放在program'sstarthere)其实这也是PyCharm推荐的做法。当你新建一个项目时,它默认创建的main.py是长这样的:在if__name__=="__main__":这一行的最左边还有一个绿色的运行按钮,点击它,程序就会从这条线开始运行。为什么很多优秀的编程语言,比如C、Java、Golang、C++,都有一个main入口函数?我认为最重要的原因之一是程序入口统一且易于阅读。第三,在多进程场景下,必须使用ifmain。比如你用多进程做并行计算,你写这样的代码:importmultiprocessingasmpdefuseful_function(x):returnx*xprint("processinginparallel")withmp.Pool()asp:results=p.map(useful_function,[1,2,3,4])print(results)当你运行它的时候,你会发现程序不停地创建进程,同时不停地报RuntimeError,即使你按CtrlC也无法终止程序。添加if__name__=="__main__":程序将按预期进行:importmultiprocessingasmpdefuseful_function(x):returnx*xif__name__=='__main__':print("processinginparallel")withmp.Pool()asp:results=p。map(useful_function,[1,2,3,4])print(results)这是为什么呢?其实我是这么理解的。Python的多程序就是启动多个Python解释器,每个Python解释器都会Import你的脚本,为子进程复制一份全局变量和函数,如果有if__name__=="__main__":,那么后面的代码不会导入,也不会重复执行。否则创建多个进程的代码会被导入执行,从而无限递归创建子进程,Python3会报RuntimeError,顺序是先创建进程,再报错,所以会不停的创建进程一直报错,按CtrlC无法终止,只能kill整个终端。这里有一个官方的解释[1]最后一句话if__name__=="__main__":虽然不是强制的,但是基于以上三个原因,我强烈推荐你这样做。它是Python社区的约定俗成,对应Python之禅:clearBetterthanobscurity。正如_作为变量名的意义是告诉看代码的人:这个变量并不重要,以后也不会用到。当你在Python脚本中看到if__name__=="__main__":时,你会意识到这是一个可执行脚本。当被其他程序导入时,这部分代码是不会执行的,多进程程序,这是必须的。本文转载自微信公众号“Python7号”,可通过以下二维码关注。转载本文请联系Python七号公众号。