习题 46: 一个项目骨架 ******************************* 这里你将学会如何建立一个项目“骨架”目录。这个骨架目录具备让项目跑起来的所有基本\ 内容。它里边会包含你的项目文件布局、自动化测试代码,模组,以及安装脚本。当你建立\ 一个新项目的时候,只要把这个目录复制过去,改改目录的名字,再编辑里边的文件就行了。 骨架内容 ======== 首先使用下述命令创建你的骨架目录: .. code-block:: bash $ mkdir projects $ cd projects/ $ mkdir skeleton $ cd skeleton $ mkdir bin $ mkdir NAME $ mkdir tests $ mkdir docs 我使用了一个叫 ``projects`` 的目录,用来存放我自己的各个项目。然后我在里边\ 建立了一个叫做 ``skeleton`` 的文件夹,这就是我们新项目的基础目录。其中叫做\ ``NAME`` 的文件夹是你的项目的主文件夹,你可以将它任意取名。 接下来我们要配置一些初始文件。以下是如何在 Linxu/OSX 环境下进行配置: .. code-block:: bash ~/projects/skeleton $ touch NAME/__init__.py ~/projects/skeleton $ touch tests/__init__.py Windows PowerShell 的配置方式如下: .. code-block:: console $ new-item -type file NAME/__init__.py $ new-item -type file tests/__init__.py 以上命令为你创建了空的模组目录,以供你后面为其添加代码。然后我们需要\ 建立一个 ``setup.py`` 文件,这个文件在安装项目的时候我们会用到它: .. literalinclude:: ex/ex46/setup.py :linenos: 编辑这个文件,把自己的联系方式写进去,然后放到那里就行了。 最后你需要一个简单的测试专用的骨架文件叫 ``tests/NAME_tests.py``\: .. literalinclude:: ex/ex46/tests/NAME_tests.py :linenos: 最终目录结构 ------------------------- 当你完成了一切准备工作,你的目录看上去应该和我这里的一样: .. code-block:: console $ ls -R NAME bin docs setup.py tests ./NAME: __init__.py ./bin: ./docs: ./tests: NAME_tests.py __init__.py 这是 unix 下看到的东西,不过 Windows 下也是一样的,如果以树状结构显示就是这个样子: .. code-block:: console setup.py NAME/ __init__.py bin/ docs/ tests/ NAME_tests.py __init__.py 从现在开始,你应该在这层目录运行命令。如果你运行 ``ls -R`` 看到的不是这个目录架构,那你所处\ 的目录就是错的。例如人们经常到 ``tests/`` 目录下运行那里的文件,但这样是行不通的。要运行你的 测试,你需要到 ``tests/`` 的上一级目录,也就是我这里显示的目录来运行。所以,如果你运行下面的命令: .. code-block:: console $ cd tests/ # WRONG! WRONG! WRONG! $ nosetests ---------------------------------------------------------------------- Ran 0 tests in 0.000s OK 这样做\ **大错特错**\!你必须在 tests 目录的上一层运行才可以,所以假设你犯了这个错误,你应该\ 用下面的方法来正确执行: .. code-block:: console $ cd .. # 离开 tests/ 目录 $ ls # CORRECT! 现在你所处的目录是正确的 NAME bin docs setup.py tests $ nosetests . ---------------------------------------------------------------------- Ran 1 test in 0.004s OK 记住这一条,因为人们经常犯这样的错误。 Python 软件包的安装 -------------------------- 你需要预先安装一些软件包,不过问题就来了。我的本意是让这本书越清晰越干净越好,\ 不过安装软件的方法是在是太多了,如果我要一步一步写下来,那 10 页都写不完,而且\ 告诉你吧,我本来就是个懒人。 所以我不会提供详细的安装步骤了,我只会告诉你需要安装哪些东西,然后让你自己搞定。\ 这对你也有好处,因为你将打开一个全新的世界,里边充满了其他人发布的 Python 软件。 接下来你需要安装下面的软件包: 1. pip -- http://pypi.python.org/pypi/pip 2. distribute -- http://pypi.python.org/pypi/distribute 3. nose -- http://pypi.python.org/pypi/nose/ 4. virtualenv -- http://pypi.python.org/pypi/virtualenv 不要只是手动下载并且安装这些软件包,你应该看一下别人的建议,尤其看看针对你的操作\ 系统别人是怎样建议你安装和使用的。同样的软件包在不一样的操作系统上面的安装方式是\ 不一样的,不一样版本的 Linux 和 OSX 会有不同,而 Windows 更是不同。 我要预先警告你,这个过程会是相当无趣。在业内我们将这种事情叫做 "yak shaving(剃牦牛)"。\ 它指的是在你做一件有意义的事情之前的一些准备工作,而这些准备工作又是及其无聊冗繁的。\ 你要做一个很酷的 Python 项目,但是创建骨架目录需要你安装一些软件包,而安装软件包之前\ 你还要安装 package installer (软件包安装工具),而要安装这个工具你还得先学会如何在\ 你的操作系统下安装软件,真是烦不胜烦呀。 无论如何,还是克服困难把。你就把它当做进入编程俱乐部的一个考验。每个程序员都会经历这\ 条道路,在每一段“酷”的背后总会有一段“烦”的。 测试你的配置 ================== 安装了所有上面的软件包以后,你就可以做下面的事情了: .. code-block:: console ~/projects/skeleton $ nosetests . ---------------------------------------------------------------------- Ran 1 test in 0.007s OK 下一节练习中我会告诉你 ``nosetests`` 的功能,不过如果你没有看到上面的画面,\ 那就说明你哪里出错了。确认一下你的 ``NAME`` 和 ``tests`` 目录下存在 ``__init__.py``\, 并且你没有把 ``tests/NAME_tests.py`` 命名错。 使用这个骨架 ================== 剃牦牛的事情已经做的差不多了,以后每次你要新建一个项目时,只要做下面的事情就可以了: 1. 拷贝这份骨架目录,把名字改成你新项目的名字。 2. 再将 NAME 模组更名为你需要的名字,它可以是你项目的名字,当然别的名字也行。 3. 编辑 setup.py 让它包含你新项目的相关信息。 4. 重命名 ``tests/NAME_tests.py`` ,让它的名字匹配到你模组的名字。 5. 使用 ``nosetests`` 检查有无错误。 6. 开始写代码吧。 小测验 ============= 这节练习没有加分习题,不过需要你做一个小测验: 1. 找文档阅读,学会使用你前面安装了的软件包。 2. 阅读关于 ``setup.py`` 的文档,看它里边可以做多少配置。Python 的安装器并不是一个\ 好软件,所以使用起来也非常奇怪。 3. 创建一个项目,在模组目录里写一些代码,并让这个模组可以运行。 4. 在 ``bin`` 目录下放一个可以运行的脚本,找材料学习一下怎样创建可以在系统下运行的 Python 脚本。 5. 在你的 ``setup.py`` 中加入 ``bin`` 这个目录,这样你安装时就可以连它安装进去。 6. 使用 ``setup.py`` 安装你的模组,并确定安装的模组可以正常使用,最后使用 ``pip`` 将其卸载。 常见问题回答 ========================== 这些说明在 Windows 下能用么? 应该可以,不过在某些版本的 Windows 里可能会碰到一点困难。自己去研究尝试,直到搞定为止。\ 或者找有经验的朋友帮你也可以。 Windows 下好像不能运行 ``nosetests`` ? 有时 Python 安装包不会把 ``C:\Python27\Script`` 加到系统 ``PATH`` 中。如果你碰到\ 这种情况,就照着 Ex0 里的说明把上述路径也加到 ``PATH`` 中。 ``setup.py`` 的配置字典中该放些什么信息进去? 读读 distutils 的文档就知道了, http://docs.python.org/distutils/setupscript.html 没法加载 ``NAME`` 模块,碰到了 ImportError. 确定你创建了 ``NAME/__init__.py`` 文件。如果你用的是 Windows,那就再检查一下是不是被\ 命名成了 ``NAME/__init__.py.txt`` ,有的编辑器会默认弄成这个样子。 为什么非要弄个 ``bin/`` 文件夹? 这只是一个标准的位置用来存放从命令行运行的脚本,但这不是存放模块的地方。 有没有实际项目的代码可以给我看看? 很多 Python 项目都用了类似的结构,你可以看看我做的这个简单项目: https://gitorious.org/python-modargs 我的 ``nosetests`` 只显示运行了一个测试。这样有没有问题? 没问题。我的输出也是这样子的。