第2章 从REPL到IDE 2.1 从 'Hello World' 开始 第一个'Hello World'的出现是在Brian Kernighan写的《A Tutorial Introduction to the Language B》书中(B语言是C语言的前身),用来将'Hello World'文字显示在计算机屏幕上,自此之后,很多程序设计语言的教学文档或书籍上,无数次地将它当作第一个范例程序。为什么要用'Hello World'来作为第一个程序范例呢?因为它很简单,初学者只要键入几行简单的程序(甚至一行),就可以要求计算机执行并得到回馈:显示'Hello World'。 本书也要从显示'Hello World'开始,然而在完成这个简单的程序之后,千万要记得探索这个简单程序之后的种种细节,千万别过于乐观地以为,你想从事的程序设计工作就是如此容易驾驭。 2.1.1 使用REPL 第一个显示'Hello World'的程序代码,我们在REPL(Read-Eval-Print Loop)环境中进行(又称为Python Shell),这是一个简单、交互式的程序设计环境。不过,虽然它很简单,但是在日后开发Python应用程序的日子里,读者会经常地使用它,因为REPL在测试一些程序片段的操作时非常方便。 现在启动“命令提示符”,直接输入python指令(不用加上任何参数),这样就会进入REPL环境,如图2-1所示。 图2-1 Python的REPL环境 现在来很快地编写一些小指令进行测试,首先做些简单的加法运算吧!从输入1+2之后按【Enter】键开始。 >>> 1 + 2 3 >>> _ 3 >>> 1 + _ 4 >>> _ 4 >>> 一开始执行了1 + 2,显示结果为3,_代表了互动环境中上一次的运算结果,方便用户在下一次运算中直接引用上一次的运算结果。 在REPL环境中,可以按【Home】键将光标移至行首,按【End】键可以将光标移至行尾。 一开始不是说要显示'Hello World'吗?接着就来在REPL环境中执行print()函数,显示指定的文字'Hello World'吧! >>> 'Hello World' 'Hello World' >>> print(_) Hello World >>> print('Hello World') Hello World >>> 在Python中,使用单引号('')括住的文字,是程序中的一个字符串(有关字符串的特性,当前先知道即可,后续章节会详加探讨)。在REPL环境中输入一个字符串后,会被当成是上一次的执行结果,因此print(_)时,_就代表'Hello World',因此和print('Hello World')的执行结果是相同的。 如果在REPL中犯错了,REPL会有些提示信息,乍一看这些信息有点神秘: >>> print 'Hello World' File "", line 1 print 'Hello World' ^ SyntaxError: Missing parentheses in call to 'print' >>> 在Python 2.x中,print是条语句(Statement),然而从Python 3.0开始,必须使用print()函数,因此print 'Hello World'在Python 3.0中会发生语法错误,其实上面的信息中SyntaxError即是告知发生了语法错误。初学时面对这类错误信息,要从找出这个错误结尾的文字开始,慢慢就能看懂发生了什么错误。 如果要获取帮助信息,那么可以输入help(),例如: >>> help() Welcome to Python 3.5's help utility! If this is your first time using Python, you should definitely check out the tutorial on the Internet at http://docs.python.org/3.5/tutorial/. Enter the name of any module, keyword, or topic to get help on writing Python programs and using Python modules. To quit this help utility and return to the interpreter, just type "quit". To get a list of available modules, keywords, symbols, or topics, type "modules", "keywords", "symbols", or "topics". Each module also comes with a one-line summary of what it does; to list the modules whose name or summary contain a given string such as "spam", type "modules spam". help> 于是进入了help()帮助页面,注意提示符变成了help>,在上面这段文字中有帮助页面的使用方式:例如想结束帮助页面,可以输入quit;想知道有哪些模块、关键词等,可以输入modules、keywords等,下面来看看Python中有哪些关键词。 help> keywords Here is a list of the Python keywords. Enter any keyword to get more help. False def if raise None del import return True elif in try and else is while as except lambda with assert finally nonlocal yield break for not class from or continue global pass help> 刚才使用过print()函数,读者会好奇它怎么使用吗?在帮助页面中输入print就可以查询了: help> print Help on built-in function print in module builtins: print(...) print(value, ..., sep=' ', end='\n', file=sys.stdout, flush=False) Prints the values to a stream, or to sys.stdout by default. Optional keyword arguments: file: a file-like object (stream); defaults to the current sys.stdout. sep: string inserted between values, default a space. end: string appended after the last value, default a newline. flush: whether to forcibly flush the stream. help> 现在输入quit,回到REPL中。实际上,在REPL中也可以直接输入help(print)来查询函数等帮助信息。 help> quit You are now leaving help and returning to the Python interpreter. If you want to ask for help on a particular object directly from the interpreter, you can type "help(object)". Executing "help('string')" has the same effect as typing a particular string at the help> prompt. >>> help(print) Help on built-in function print in module builtins: print(...) print(value, ..., sep=' ', end='\n', file=sys.stdout, flush=False) ...略 >>> 如果要离开REPL环境,可以执行quit()函数。如果只是要执行一个程序片段,又不想麻烦地进入REPL,可以在使用python指令时加上-c参数,之后接上使用""包含的程序片段。例如: >>> quit() C:\Users\Jun>python -c "print('Hello World')" Hello World C:\Users\Jun>python -c "help(print)" Help on built-in function print in module builtins: print(...) print(value, ..., sep=' ', end='\n', file=sys.stdout, flush=False) ...略 C:\Users\Jun> 在Python官方网站(www.python.org)首页,也提供了一个互动环境,临时要测试一个程序片段,又不想安装Python或找个装有Python的计算机时,启动浏览器就可以使用了,如图2-2所示。 图2-2 Python官网上提供的在线REPL环境 2.1.2 编写Python源码 我们总是要打开一个源码文件,正式一点地编写程序吧?在正式编写程序之前,请先确定自己可以看到文件的扩展名,在Windows下默认不显示扩展名,这会造成重新命名文件时的困扰,如果当前在“文件资源管理器”下无法看到扩展名,Windows 7下请依次选择 “组织→文件夹和搜索选项”,在Windows 8或10中则可以依次选择“查看→选项”,之后切换至“查看”标签,取消勾选“隐藏的项目”,同时确保勾选了“文件扩展名”选项,如图2-3所示。 图2-3 选择显示出“文件扩展名” 接着选择一个文件夹来编写Python源码文件,本书都是在C:\workspace文件夹中编写程序,请新建“文本文件”(也就是.txt文件),并重新命名文件为“hello.py”,由于将文本文件的扩展名从.txt改为.py,系统会询问是否更改扩展名,请确认更改。如果是在Windows中第一次安装Python,而且按照本章之前介绍的方式安装,那么会看到文件图标变换为以下样式,这个图标上的吉祥物是两只小蟒蛇(因为Python也有蟒蛇之意),如图2-4所示。 图2-4 更改扩展名为.py后的图标 尽管Python有蟒蛇之意,不过Guido van Rossum 曾经表示,Python这个名称其实是取自他热爱的BBC著名喜剧电视剧《Monty Python's Flying Circus》,Python官方网站的FAQ也记录着这件事。 docs.python.org/3/faq/general.html#why-is-it-called-python 这个FAQ的下一个还是很幽默地列出了Do I have to like “Monty Python’s Flying Circus”?这个问题,答案是No, but it helps。 如图2-4中可以看到的,如果在.py文件上右击鼠标,可以选择“Edit with IDLE”选项来打开这个文件进行编辑,IDLE是Python官方内建的编辑器(本身也是使用Python编写而成),这会比使用Windows内建的记事本编写Python程序要好一些,读者可以如图2-5所示来编写程序代码。 图2-5 使用Python IDLE来编写第一个Python程序 很简单的一个小程序,只是使用Python的print()函数输出文字,执行时print()函数默认会在控制台(Console)显示要输出的文字。 接着选择菜单“File/Save”选项来保存文件。虽然可以直接在IDLE中选择“Run/Run Module”选项来启动Python的REPL来运行程序。不过,下面要使用“命令提示符”程序。请启动“命令提示符”程序,工作文件夹切换至C:\workspace(执行命令cd c:\workspace),然后如图2-6所示使用python指令运行程序。 图2-6 运行第一个Python程序 2.1.3 哈啰!世界! 就程序设计语言来说,Python确实是个容易入门的语言。不过,无论任何一个领域都请记得“事物的复杂度不会凭空消失,只会从一个事物转移到另一个事物”,在程序设计这个领域也是如此。如果纯粹只是想“营销”Python这门语言给读者,介绍完刚才的Hello World程序后,笔者就可以开始“歌颂”Python语言的美好了。 Python有其“美好”的一面,实际上也有其会面临的难题,如果读者将来打算发挥Python更强大的功能,或者需要解决更复杂的问题,就需要进一步深入探索Python。在本书之后的章节,会谈到Python一些比较深入的议题。 至于现在,作为中文世界的开发者,想稍微触碰一下复杂度,除了显示Hello World之外,不如再来试试显示“哈啰!世界!”如何?请创建一个hello2.py文件,这次不要使用IDLE,直接使用Windows的“记事本”来编写这个程序,如图2-7所示。 图2-7 用记事本来编写第二个Python程序 接着在控制台中运行python hello2.py,不幸的是,这次出现了错误,如图2-8所示。 图2-8 运行出错了 UTF-8 错误的信息中显示SyntaxError,也就是语法错误,原因在于Python 3之后,python解释器预期的源码文件的编码必须是UTF-8(Python 2.x预期的是ASCII)。然而,Windows简体中文版中的记事本默认的编码是MS936(兼容于汉字国标码GBK),两者对于汉字字符的字节编码方式并不相同,python解释器如果看到无法解释的字节,就会发生了SyntaxError。 UTF-8是目前很流行的文字编码方式,现在不少文本编辑器默认会使用UTF-8,像刚才使用的IDLE,相同的程序代码使用IDLE编写和保存,运行时就不会发生错误。然而问题在于,许多人不使用IDLE,读者将来也可能会换用其他编辑器,在使用前必须了解这个事实。 如果读者尚不知道 UTF-8 是什么,建议先看看“哪来的纯文本文件?”“Unicode与UTF”“UTF-8”这三个文档。 openhome.cc/Gossip/Encoding/TextFile.html openhome.cc/Gossip/Encoding/UnicodeUTF.html openhome.cc/Gossip/Encoding/UTF8.html Windows的记事本可以在“另存为”时选择文字编码为UTF-8,如图2-9所示,这是解决问题的一个方式。 图2-9 记事本可在“另存为”时选择文字编码为UTF-8 Windows中内建的记事本应用程序并不是很好用,笔者个人习惯用Notepad++(notepad-plus-plus.org),这个免费并强大的编辑器在编辑文件时,可以直接在菜单“编码”中选择文字编码,如图2-10所示。 图2-10 设置Notepad++的文字编码方式 设置源码的编码 若不想将文件的文字编码设置为UTF-8,另一个解决方式是在源码的第一行使用注释方式来设置编码。最简单的设置方式如图2-11所示。 图2-11 设置Python源码文件的编码 在Python源码文件中,#开头代表这是一行注释,#之后不会被当成是程序代码的一部分,如图2-11所示加上#coding: MS936之后,就可以正确地运行程序了,如图2-12所示。 图2-12 加上#coding: MS936之后,就可以正确地运行程序了 在hello2.py的程序代码中,input()是个函数(Python 2.x中使用的是raw_input()),可用来获取用户输入的文字,调用函数时指定的文字会作为控制台中的提示信息,在用户输入文字并按【Enter】键后,input()函数会以字符串返回用户输入的文字,在这个程序中将之赋值给变量name,之后使用print()函数按序显示'哈啰'、name与'!'。 为什么说是最简单的设置方式呢?将来读者也许还会看到其他的编码设置方式,例如: # -*- coding: GBK -*- 或者是: # vim: set fileencoding=GBK : 也许读者还会看到更多的方式,这是因为python解释器只要在注释中看到coding=或者coding: 出现就可以了。因此,就算读者在第一行编写了#orz coding=MS936或者#XDcoding: MS936,python解释器也都可以正确找出文字编码的设置。 这是为了顺应各种编辑器的特性,如果有兴趣,可以参考PEP 0263: www.python.org/dev/peps/pep-0263/ 这个文档中有说明,python解释器会使用下面这段正则表达式(Regular expression)来提取文字编码的设置。 ^[ \t\v]*#.*?coding[:=][ \t]*([-_.a-zA-Z0-9]+) 本书第11章会介绍什么是正则表达式,以及在Python中如何使用它。 2.2 初识模块与软件包 对于初学者来说,通常只需要一个.py源码文件就可以应付各种范例程序的代码量。然而,实际的应用程序需要的代码量远比范例程序要多得多,只使用一个.py源码文件来编写,势必会造成程序代码管理上的混乱,读者必须学会根据功能将程序代码划分到不同的模块(Module)中编写,对于功能相近或彼此辅助的模块,也要知道如何使用软件包(Package)来加以管理。 模块与软件包也有一些要知道的细节,这一节将只介绍简单的入门,这样足以完成前面几个章节的学习,更详细的模块与软件包说明,将会在第5章与第14章详细介绍。 2.2.1 模块简介 有一个事实也许会令人惊讶,其实读者到这里已经编写过模块了,每个.py文件本身就是一个模块,当读者编写完一个.py文件,如果别人打算直接分享你的成果,只需要在他编写的.py文件中导入(import)就可以了。举个例子来说,若想在一个hello3.py文件中直接使用前面编写好的hello2.py文件,可以编写如图2-13所示的程序。 图2-13 导入模块 每个.py文件的主文件名就是模块名称,想要导入模块时必须使用import关键词来指定模块名称。若要引用模块中定义的名称,则必须在名称前加上模块名称与一个“.”符号,例如hello2.name。接下来直接执行hello3.py,看看会有什么结果,如图2-14所示。 图2-14 导入了另一模块后的程序运行结果 运行结果中前两行显示的就是hello2.py中编写的内容,即按照import的顺序导入的程序代码先被执行,接着才执行hello3.py中import之后的程序代码。 此时如果查看.py文件所在的文件夹,就会发现多了一个__pycache__文件夹,当中会有.pyc文件,这是CPython将.py文件编译后的字节码文件。如果之后再次导入同一个模块,检测到源码文件没有更改过,就不会再对源码重头开始进行语义和语法解析等操作,可以直接从字节码开始解释,以加快解释执行的速度。 类似地,Python本身提供了标准链接库,如果需要这些链接库中的某个模块功能,那么可以将模块导入。例如,若想要获取命令行参数(Command-line argument),可以通过sys模块中的argv列表(list),如图2-15所示。 图2-15 获取命令行参数 由于argv定义在sys模块中,在import sys后,就必须使用sys.argv来引用,sys.argv列表中的数据引用时必须指定索引(Index)号码,这个号码实际上从0开始,然而sys.argv[0]保存的是源码的文件名,就上面的例子来说,保存的是'hello4.py',若要引用命令行参数,则按序从sys.argv[1]开始引用即可。这个程序的运行结果如图2-16所示。 图2-16 获取命令行参数的范例 如果有多个模块需要import,除了逐行import之外,也可以在单独一行中使用逗号(,)来分隔开各个模块的名称。例如: import sys, email 使用模块来管理源码,有利于源码的重复使用而且可以避免混乱,然而有些函数、类等经常使用,每次都要import就显得很麻烦,因此这类常用的函数、类等也会被整理在一个__builtins__模块中,在__builtins__模块中的函数、类等名称都可以不用import而直接引用,而且不用加上模块名称作为前置,例如之前使用过的print()、input()函数。 想知道还有哪些函数或类吗?可以在REPL中使用dir()函数查询__builtins__模块,dir()函数会将可用的名称列出,例如dir(__builtins__),如图2-17所示。 图2-17 查询__builtins__模块 在官方网站文件中,也有一些__builtins__模块中函数、常数的说明文件。 docs.python.org/3.5/library/functions.html docs.python.org/3.5/library/constants.html 2.2.2 设置PYTHONPATH 如果已经学会了使用模块,现在有个小问题,要想引用他人编写好的模块,一定要将.py文件存放到当前的工作文件夹中吗?举个例子来说,当前的.py文件都存放在C:\workspace,如果执行python指令时也是在C:\workspace,基本上不会有问题,如果在其他文件夹就会出错,如图2-18所示。 图2-18 找不到hello模块 在2.1.1小节中讲过,python -c可以指定一段小程序来运行,因此python -c "import hello"就相当于在某个.py文件中执行了import hello,因此这里用来测试是否可以找到指定模块。可以看到,在找不到指定模块时,会发生ImportError错误。 如果想将他人提供的.py文件存放到其他文件夹(例如lib文件夹)中加以管理,可以设置PYTHONPATH环境变量来解决这个问题。python解释器会在环境变量设置的文件夹中寻找是否有指定模块名称对应的.py文件。例如,在图2-19中设置好环境变量,就不会再发生上述的ImportError错误。 图2-19 设置PYTHONPATH环境变量 在Windows中,可以使用SET PYTHONPATH=路径1;路径2的方式来设置PYTHONPATH环境变量,多个路径时中间使用分号(;)来分隔。实际上,python解释器会根据sys.path列表中的路径来寻找模块,以当前的设置来看,sys.path会包含以下内容,如图2-20所示。 图2-20 查询sys.path 如果Windows中安装了多个版本的Python环境,也可以按照类似方式设置PATH环境变量,例如SET PATH=Python环境路径,这样就可以切换执行不同版本的python解释器。 因此,如果想要动态地管理模块的寻找路径,那么也可以通过程序更改sys.path的内容来达到目的。例如在没有对PYTHONPATH设置任何信息的情况下,在进入REPL后,可以如图2-21所示进行设置。 图2-21 动态设置sys.path 在图2-21中可以看到,sys.path.append('c:\workspace')对sys.path新增了一条路径信息,因此之后import hello时,就可以在c:\workspace找到对应的hello.py了。 2.2.3 使用软件包管理模块 现在读者所编写的程序代码可以分别放在各个模块之中,在源码管理上好一些了,但还不是很好,就如同你会分不同文件夹来存放不同作用的文件那样,模块也应该分门别类地存放。 举例来说,一个应用程序中会有多个类彼此合作,也有可能由多个团队共同分工来完成应用程序的某些功能块,然后再组合在一起。如果应用程序是多个团队共同合作开发的,若不分门别类地存放这些模块,例如A部门写了个util模块,B部门也写了个util模块,当他们要将应用程序整合时,如果都将模块存放在同一个lib目录中,就会发生同名的util.py文件彼此覆盖的问题。 两个部门各自创建文件夹存放自己的util.py文件,然后在PYTHONPATH中设置路径的方式是行不通的,因为执行import util时,只会使用通过PYTHONPATH环境变量找到的第一个util.py,真正需要的方式是能够import a.util或import b.util来导入对应的模块。 为了示范软件包的管理,我们来创建一个新的hello_prj文件夹,这就像新创建应用程序项目时,必须有个项目文件夹来管理项目的相关资源。假设读者在hello_prj中新增一个openhome软件包,那么请在hello_prj中建立一个openhome文件夹,再在openhome文件夹中创建一个__init__.py文件,如图2-22所示。 图2-22 创建openhome软件包 注意!文件夹中一定要有一个__init__.py文件,该文件夹才会被视为一个软件包。在软件包的高级管理中,__init__.py中其实也可以编写程序,不过目前请保持__init__.py文件内容为空。 接着,请将2.1.3小节编写的hello2.py文件复制到openhome软件包中,然后将2.2.1小节编写的hello3.py文件复制到hello_prj项目文件夹中,并修改hello3.py,如图2-23所示。 图2-23 导入软件包中的模块 主要的修改就是import openhome.hello2与openhome.hello2.name,也就是模块名称前加上了软件包名称,这就说明了软件包名称会成为命名空间的一部分。 当python解释器看到import openhome.hello2时,会寻找sys.path的路径里是否在某个文件夹中含有openhome文件夹,如果找到了,就再进一步确认其中是否有一个__init__.py文件,如果有就确认有openhome软件包了,接着查看其中是否有hello2.py,如果找到了,就可以顺利完成模块的import。 要执行hello3.py,请在控制台(即“命令提示符”程序)中切换至c:\workspace\hello_prj文件夹,运行范例的结果如图2-24所示。 图2-24 导入软件包中模块的范例运行结果 由于软件包名称会成为命名空间的一部分,就之前A、B两部门的例子来说,可以分别创建a软件包与b软件包,当中存放各自的util.py,当两个部分的a、b两个文件夹放到同一个lib文件夹时,就不会发生util.py文件彼此覆盖的问题。在导入模块时,可以分别import a.util与import b.util,如果想引用各自模块中的名称,那么也可以使用a.util.some、b.util.other来区别。 如果模块数量很多,也可以创建多层次的软件包,也就是软件包中还会有软件包,在这种情况下,每个担任软件包的文件夹与子文件夹中,各要有一个__init__.py文件。举例来说,如果想要创建openhome.blog软件包,那么openhome文件夹中要有一个__init__.py文件,而openhome/blog文件夹中也要有一个__init__.py文件。 还记得1.2.3小节“认识安装的内容”中讲过,在安装Python的lib文件夹中,包括了许多标准链接库的源码文件吗?lib文件夹包含在sys.path中,这个文件夹中也使用了一些软件包来管理模块,其中还有个site-packages文件夹用来安装Python的第三方程序库,这个文件夹也包含在sys.path中,通常第三方程序库也会使用软件包来管理相关的模块。 2.2.4 使用import as与from import 使用软件包管理解决了实体文件与import模块时命名空间的问题。然而,有时软件包名称加上模块名称会使得引用某个函数、类等时必须编写冗长的前置,如果嫌麻烦,那么可以使用import as或者from import来解决这个问题。 import as重新命名模块 如果想要改变被导入模块在当前模块中的变量名称,可以使用import as。例如可修改之前hello_prj文件夹中的hello3.py,如下: hello_prj2 hello3.py import openhome.hello2 as hello print('今天要来点什么不同的吗?', hello.name, '!') 在上面的范例中,import openhome.hello2 as hello将openhome.hello2模块重新命名为hello,接下来就可以使用hello这个名称来直接引用模块中定义的名称。 from import直接导入名称 使用import as是将模块重新命名。然而,引用模块中定义的名称时还是得加上名称作为前置,如果仍然嫌麻烦,那么可以使用from import直接将模块中指定的名称导入。例如: hello_prj3 hello.py from sys import argv print('哈啰!', argv[1], '!') 在这个范例中,直接将sys模块中的argv名称导入到hello模块中,也就是当前的hello.py文件中,接下来就可以直接使用argv,而不是sys.argv来存取命令行参数。 如果有多个名称想要直接导入到当前模块,除了逐行from import之外,还可以在单独一行中使用逗号(,)来分隔它们。例如: from sys import argv, path 你可以更“偷懒”一些,用以下的from import语句来导入sys模块中全部的名称。 from sys import * 不过这个方式有点危险,因为很容易引发名称冲突问题,如果两个模块中正好都有相同的名称,那么比较后面from import的名称会覆盖先前的名称,导致发生一些意外的程序错误。因此,除非你是在编写一些简单且内容不长的指令脚本,否则不建议使用from xxx import *的方式。 from import除了从模块导入名称之外,也可以从软件包导入模块,例如,如果openhome软件包下有个hello模块,就可以如下导入模块名称。 from openhome import hello 2.3 使用IDE 在开始使用软件包管理模块后,必须建立与软件包对应的实体文件夹层次,还要自行添加__init__.py文件,这其实有点麻烦,可以考虑使用集成开发环境(Integrated Development Environment,IDE),由IDE代劳一些软件包与相关资源管理的工作,以便提升工作效率。 2.3.1 下载、安装PyCharm 在Python的领域中,有为数不少的IDE,然而使用哪个IDE,必须根据开发的应用程序特性,或者基于一些团队管理等因素来决定,有时其实也是个人喜好的问题,下面介绍一些有人推荐的或使用过的IDE。 ? PyCharm(www.jetbrains.com/pycharm/) ? PyDev(www.pydev.org/) ? Komodo IDE(komodoide.com/) ? Spyder(code.google.com/archive/p/spyderlib/) ? WingIDE(wingware.com/) ? NINJA-IDE(www.ninja-ide.org/) ? Python Tools for Visual Studio(pytools.codeplex.com/) 有时甚至会考虑使用一些功能强大的编辑器,加上一些插件来组装出自己专用的IDE,在Python这个领域,要使用IDE或是编译器,也是个经常论战的话题,这当中也有一些值得思考的要点,有兴趣可以参考“IDE、编辑器的迷思”这篇文章。 openhome.cc/Gossip/Programmer/IDEorEditor.html 为了能与本书谈过的概念相衔接,作者在这里选择使用PyCharm进行基本介绍,它提供了社区版本,对于入门用户练习来说,完全可以胜任,读者可以直接连接到www.jetbrains.com/pycharm/download/,单击页面右边“Community”下面的“Download”按钮,即可进行下载,如图2-25所示。 图2-25 下载PyCharm社区版本 在编著本书的时候,可下载的PyCharm Community版本是2016.2.1,文件为pycharm-community-2016.2.1.exe。由于下载后是个.exe文件,读者必须如1.2.2小节介绍的方式“解除锁定”,并以“以管理员身份运行”进行安装。安装的默认路径是C:\Program Files (x86)\JetBrains\PyCharm Community Edition 2016.2.1,基本上只需要一直单击“Next”与“Install”按钮就可以完成安装。读者可以根据自己的需要采用默认安装的目标盘和路径或者选择自己指定的安装目录和路径。 在安装完成后,应用程序菜单中会有个JetBrains PyCharm Community Edition 2016.2.1的图标,单击该图标就可以启动PyCharm,初次启动时会显示一个提示画面,询问是否导入前一版本的PyCharm设置,默认是不导入。由于这是初次安装,直接单击“OK”按钮即可,如图2-26所示。 图2-26 初次启动PyCharm时显示的提示画面 下一个显示画面是主题设置,如果没有特别偏好的主题,也是直接单击“OK”按钮接受默认值,如图2-27所示,接下来就可以准备创建新项目了。 图2-27 接受默认的主题 2.3.2 IDE项目管理基础 IDE基本上就是建立在当前安装的Python环境之上,无论使用哪个IDE,最重要的是知道它如何与现有的Python环境对应,只有认清这样的对应关系,才不会沦为只知道IDE上一些傻瓜式的操作,却不明了各个操作背后的原理,这也是这里要介绍IDE的缘故。 之前在介绍软件包与模块时提到,我们会创建一个项目文件夹,在其中管理软件包、模块或其他相关资源。因此,使用IDE的第一步就是创建新项目,请先单击“Create New Project”,如图2-28所示。 图2-28 创建新项目 下一步是要决定项目文件夹的位置与使用的Python解释器,未来你的计算机中可能安装了不止一个版本的Python环境,在IDE中通常可以管理、选择不同的Python环境来开发程序,这也是使用IDE的好处之一。在这里选择在C:\workspace\hello_prj4中创建新项目,如图2-29所示。 图2-29 设置项目文件夹与解释器的版本 接着单击“Create”按钮就可以创建项目了,如图2-30所示。 如图2-30中可看到的,在“External Libraries”中可直接浏览当前使用的python解释器、链接库的位置等信息。读者可以试着执行“New/Python Package”来创建一个openhome软件包,在该软件包上执行“New/Python File”创建一个hello.py,编写一小段程序并执行,如图2-31所示。 图2-30 项目的基本结构 图2-31 创建软件包、模块与运行 可以看到,在创建软件包时,IDE会自动创建__init__.py,想要执行模块,可以用鼠标右击程序,再单击弹出的快捷菜单中的“Run 'hello'”选项,其中hello会根据当前的模块名称而有所不同,运行过的程序结果会显示在下面的窗格中,当中明确地显示了执行的过程,非常方便。 读者也许想要设置命令行参数,可以通过依次选择菜单和菜单项“Run/Run”来设置,期间会出现一个“Run”设置窗格,用于选择要设置哪个模块,如图2-32所示。 图2-32 编辑Run的设置 在单击“Edit”之后,会出现“Edit configuration settings”对话框,从中可以发现用于设置python解释器的一些选项,像PYTHONPATH之类的设置,其中命令行参数可以在“Script parameters”中设置,如图2-33所示。 图2-33 设置python解释器的相关选项 由于本书篇幅有限,不可能详细地介绍IDE的每个功能。不过,在开始使用一个IDE时,基本上也就是这样的:逐一找出与Python环境的对照,而且要知道哪个功能在没有使用IDE时是如何设置的,通过这样的探索,才能一方面获得IDE的方便性,另一方面又不至于被IDE限制。 在知道怎么编写、执行'Hello World'程序之后,接下来就要更进一步地了解 Python 程序设计语言,从下一章开始介绍Python语言的基本元素,例如内建类型、流程控制语句等。 2.4 重点复习 REPL环境是一个简单、交互式的程序设计环境,在测试一些程序片段时非常方便。 在Python 2.x中,print是条语句(Statement),然而从Python 3.0开始,必须使用print()函数。 Python 3之后,python解释器预期的源码文件的编码必须是UTF-8(Python 2.x预期的是ASCII)。若不想将文件的文字编码设置为UTF-8,另一个解决方式是在源码的第一行使用注释来设置编码信息,python解释器只要在注释中看到coding=或者coding: 即可。 在Python源码文件中,#开头代表这是一行注释,#之后不会被当成程序代码的一部分。 每个.py文件本身就是一个模块,文件的主文件名就是模块名称,想要导入模块时必须使用import关键词指定模块名称,若要引用模块中定义的名称,则必须在名称前加上模块名称与一个“.”符号。 想要获取命令行参数,可以通过sys模块中的argv列表。sys.argv列表中的数据引用时必须指定索引号码,这个号码实际上从0开始,sys.argv[0]保存的是源码文件名,如果要引用命令行参数,就按序从sys.argv[1]开始引用。 如果有多个模块需要import,除了逐行import外,还可以在单独一行中使用逗号(,)来分隔开模块。 在__builtins__模块中的函数、类等名称都可以不用import(导入)直接引用,而且不用加上模块名称作为前置。 python解释器会在PYTHONPATH环境变量设置的文件夹中寻找是否有指定模块名称对应的.py文件。python解释器会根据sys.path列表中的路径来寻找模块。如果想要动态地管理模块的寻找路径,也可以通过程序更改sys.path的内容来达到此目标。 文件夹中一定要有一个__init__.py文件,该文件夹才会被视为一个软件包。软件包名称会成为命名空间的一部分。可以创建多层次的软件包,也就是软件包中还会有软件包,每个担任软件包的文件夹与子文件夹中各要有一个__init__.py文件。 如果想要改变被导入模块在当前模块中的变量名称,可以使用import as。可以使用from import直接将模块中指定的名称导入。 除非是在编写一些简单且内容不长的指令脚本,否则不建议使用from xxx import *的方式,以免引发命名空间冲突的问题。