练习 46 - 一个项目骨架 - 笨办法学Python3

练习 46. 一个项目骨架

这个练习你将学习如何创建一个好的项目“骨架”(skeleton)目录。这个骨架目录具备让项目跑起来的所有基本内容。它里边会包含你的项目文件布局、自动化测试代码、模块,以及安装脚本。当你建立一个新项目的时候,只要把这个目录复制过去,改改目录的名字,再编辑里边的文件就行了。

macOS/Linux 设置

在开始这个练习之前,你需要用一个叫做 pip3.6(或者 pip)的工具为 Python 安装一些新的模块。python3.6 的安装中已经包含了 pip3.6 命令。你可以通过如下命令来验证一下:

$ pip3.6 list 
pip (9.0.1)
setuptools (28.8.0)
$

如果看到任何弃用警告,可以忽略它。您可能还会看到安装了其他工具,但是基本的应该是 pip 和 setuptools。一旦你验证了这一点,你就可以安装 virtualenv:

$ sudo pip3.6 install virtualenv Password:
Collecting virtualenv
Downloading virtualenv–15.1.0–py2.py3–none–any.whl (1.8MB) 100% ||||||||||||||||||||||||||||||||| 1.8MB 1.1MB/s
Installing collected packages: virtualenv Successfully installed virtualenv– 15.1.0
$

这是用于 Linux 或者 macOS 系统的,如果你用的是 Linux/macOS, 你可以运行如下命令来确保你安装了正确的 virtualenv:

$ whereis virtualenv
/Library/Frameworks/Python.framework/Versions/3.6/bin/virtualenv

您应该能在 macOS 上看到类似上面的内容,但是 Linux 上可能不一样。在 Linux 上,你可能有一个实际的 virtualenv3.6 命令,或者你最好从你的包管理系统(package management system)中为它安装一个包(package)。

一旦安装了 virtualenv,你就可以用它来创建一个“伪” Python 安装,从而更容易管理不同项目的包版本。首先,运行如下命令,我等会儿会解释它的作用:

$ mkdir ~/.venvs
$ virtualenv –system–site –packages ~/.venvs/lpthw
$ . ~/.venvs/lpthw/bin/activate 
(lpthw) $

每一行发生的事情如下:

  1. 你在你的 HOME ~/ 地址下创建了一个叫做 .venvs 的目录,用来存储你的虚拟环境。

  2. 你运行了 virtualenv 然后告诉它要包含 system site packages (-- system-site-packages),然后指导它在 ~/.venvs/lpthw 中创建 virtualenv

  3. 然后你在 bash 中用 . 运算符来获得 lpthw 虚拟环境,后面跟着 ~/.venvs/lpthw/bin/activate 脚本。

  4. 最后,你的提示变成了包含 (lpthw),这样你就知道了你正在使用虚拟环境。

现在你可以看到东西被安装在哪里:

(lpthw) $ which python
/Users/zedshaw/.venvs/lpthw/bin/python 
(lpthw) $ python
Python 3.6.0rc2 (v3.6.0rc2:800a67f7806d, Dec 16 2016, 14:12:21)
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> quit() 
(lpthw) $

你可以看到运行中的 python 被安装在 /Users/zedshaw/.venvs/lpthw/bin/python 目录,而不是原来的地址。这样还免去了要输入 python3.6 的麻烦,因为它把二者都安装了:

$ which python3.6
/Users/zedshaw/.venvs/lpthw/bin/python3.6 
(lpthw) $

你会发现 virtualenvpip 命令也一样。这个设置的最后一步是安装 nose,一个我们要在练习中用到的测试框架。

$ pip install nose 
Collecting nose
    Downloading nose—1.3.7—py3—none—any.whl (154kB)
        100% | ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ | 163kB 3.2mb/s Installing collected packages: nose
Successfully installed nose —1.3.7 
(lpthw) $

Windows 10 设置

Windows 10 的安装会比 Linux 或者 macOS 简单一些,但是前提是你只安装了一个版本的 Python。如果你有两个版本:Python 3.6 和 Python 2.7,那你自己靠自己了,因为搞多重安装太复杂了。如果你一直跟着这本书学的话,你应该只有 Python 3.6,然后你可以这样做。

首先,切换到你的 home 目录,然后确保你正在运行正确版本的 Python:

> cd ~
> python
Python 3.6.0 (v3.6.0:41 df79263a11 , Dec 23 2016, 08:06:12) [MSC v.1900 64 bit (AMD64)] on Win32
Type "help", "copyright", "credits" or "license" for more informa
>>> quit()

然后运行 pip 确保你已经做了基本的安装:

> pip list 
pip (9.0.1)
setuptools (28.8.0)

你可以安全地忽略任何弃用警告,如果你安装了其他的包也没有关系。接着,安装 virtualenv 来为这本书接下来的内容设置一个虚拟环境:

> pip   install virtualenv 
Collecting virtualenv
    Using cached virtualenv —15.1.0—py2.py3—none—any.whl Installing collected packages : virtualenv 
Successfully installed virtualenv — 15.1.0

安装好 virtualenv 之后,你需要创建一个 .venvs 目录,并填入一个虚拟环境:

> mkdir .venvs
> virtualenv --system-site-packages .venvs/lpthw 
Using base prefix
    'c:\\users\\zedsh\\appdata\\local\\programs\\python\\python36 
New python executable in
    C:\Users\zedshaw\.venvs\lpthw\Scripts\python.exe 
Installing setuptools, pip, wheel ... done.

这两行命令创建了一个 .venvs 文件夹来存储不同的虚拟环境,然后还创建了你的第一个虚拟环境 lpthw。一个虚拟环境(virtualenv)是一个用来运行软件的虚构的地方,这样你就有了针对每个项目包的不同版本。设置好 virtualenv 之后你需要激活它:

> .\.venvs\lpthw\Scripts\activate

这个命令会让 PowerShell 运行 activate 脚本,这个脚本会为你当前的 shell 配置 lpthw 虚拟环境。每次你想用你在这本书里的软件,你都要运行这个命令。你会看到 PowerShell 中的下一行命令提示符前面已经有了一个 (lpthw),这表明了你正在使用的虚拟环境。最后,你只需要安装 nose 来运行随后的测试:

(lpthw) > pip install nose 
Collecting nose
    Downloading nose —1.3.7—py3—none—any.whl (154kB)
        100% | ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ | i63kB i.2mb/s Installing collected packages: nose
Successfully installed nose—1.3.7 
(lpthw) >

你会看到,这样就安装了 nose,不过 pip 会把它安装在你的 .venvs\lpthw 虚拟环境中,而不是主系统的目录。这可以让你为每个项目安装相互冲突的 Python 包版本,而不会影响主系统的配置。

创建项目骨架目录

首先,用以下这些命令创建你的项目骨架结构:

$ mkdir projects
$ cd projects/
$ mkdir skeleton
$ cd skeleton
$ mkdir bin, NAME, tests, docs

ai酱注:这里原文是 mkdir bin Name tests docs 无法正常运行,作者本意是创建平行文件夹,所以用 , 隔开。

我用一个叫做 projects 的目录来存储所有我正在使用的变量。在这个目录下,我创建了 skeleton 目录,并把我项目的一些基础文件放了进去。这个 NAME 可以被重命名为任何你想给你项目的主模块取的名字。

接着,我们需要设置一些初始化文件,以下是 Linux/macOS 系统上的操作:

$ touch NAME/__init__.py
$ touch tests/__init__.py

以下是 Windows PowerShell 上的操作:

$ new-item —type file NAME/__init__.py
$ new-item —type file tests/__init__.py

这样就创建了一个空的 Python 模块目录,我们可以把我们的代码放进去。然后我们需要创建一个 setup.py 以便在之后需要的时候来安装我们的项目:

ai酱注:该文件创建在当前 skeleton 目录下,可以参考前述创建文件的命令来创建。

setup.py

1   try:
2       from setuptools import setup
3   except ImportError:
4       from distutils.core import setup 
5
6   config = {
7       'description': 'My Project',
8       'author': 'My Name',
9       'url': 'URL to get it at.',
10      'download_url': 'Where to download it.',
11      'author_email': 'My email.', 
12      'version': '0.1',
13      'install_requires': ['nose'],
14      'packages': ['NAME'],
15      'scripts': [],
16      'name': 'projectname' 
17  }
18
19  setup(**config)

编辑这个文件,在其中填上你的联系信息,并且保证当你复制该文件的时候它能正常运行。

最后,你需要一个简单的骨架文件来测试,文件名为:tests/NAME_tests.py :

NAME_tests.py

1   from nose.tools import *
2   import NAME 
3
4   def setup():
5       print("SETUP!") 
6
7   def teardown():
8       print("TEAR DOWN!") 
9
10  def test_basic():
11      print("I RAN!")

46.3.1 最终目录结构

当你完成以上所有设置,你的目录应该像下面这样:

skeleton /
 
NAME/
    __init__.py 
bin/
docs/ 
setup.py 
tests/
    NAME_tests. py
    __init__.py

从现在开始,你应该从这个目录中运行你的命令。如果你看不到,可以输入 ls -R,如果你没看到同样的结构,那应该是搞错了当前目录。比如,人们通常在 tests/ 下运行文件,这肯定行不通。要运行你的应用的测试,你需要处在 tests/ 目录的上一层,所以如果你这样:

$ cd tests/ # WRONG! WRONG! WRONG!
$ nosetests
-----------------------
Ran 0 tests in 0.000 s OK

那就大错特错了,你得在 tests 的上一层目录。要是你犯了这个错误,你可以这样改正:

$ cd .. # get out of tests/ 
$ ls    # CORRECT! you are now in the right spot
NAME    bin docs    setup.py
$ nosetests
.
-----------------------
Ran 1 test in 0.004s OK

记住这一点,因为人们经常犯这样的错误。

测试你的 Setup

当你安装好了所有东西之后,你应该可以运行这个:

$ nosetests
.
-----------------------
Ran 1 test in 0.007s OK

我会在下个练习中给你解释 nosetests 是做什么的,但是现在,你如果没看到这个,那你可能哪个地方搞错了。确保你把 __init__.py 文件放在了你的 NAME 目录和 tests 目录下面,并且确保你把 tests/NAME_tests.py 放在了正确的位置。

使用这个骨架

现在你已经完成了一连串的动作。任何时候当你想要开始一个新项目,只需要这样做:

  1. 创建一个骨架目录的副本,以你的新项目名称命名。

  2. 用你的新项目名重命名 NAME 目录,或者其他你想用的名字,来调用你的根模块。

  3. 编辑你的 setup.py 文件,为你的新项目填入相应的信息。

  4. 重命名 tests/NAME_tests.py 文件,跟你的模块文件保持一致。

  5. 再次用 nosetests 确保所有文件都能正常运行。

  6. 开始编写代码。

课后测试

这个练习没有附加练习,但是你必须完成一个测试:

  1. 读一读如何使用你所安装的所有东西。

  2. 读一读 setup.py 文件及其内容。警告:它不是一个写得很好的软件,所以可能会很难用。

  3. 创建一个项目,并且开始把代码放入模块,然后让这个模块运行起来。

  4. 在 bin 目录中放一个可以运行的脚本。读一读你如何能让一个 Python 脚本在你的系统中正常运行。

  5. 在你的 setup.py 文件中加上你所创建的 bin 脚本,以使其得到安装。

  6. 用你的 setup.py 来安装你自己的模块,确保它能正常运行,然后使用 pip 来卸载它。

常见问题

这些指导适用于 Windows 吗? 适用的,不过还取决于你的 Windows 版本。有些版本可能会让你在安装的时候遇到一些麻烦。你可以通过搜索来解决,或者找一个对 Python+Windows 比较有经验的朋友来帮你解决。

我应该在我的 setup.py 配置文件中放些什么呢? 确保你阅读了该链接中的发布工具(distutils)文档:http://docs.python3.6.org/distutils/setupscript.html.

我没办法引入 NAME 模块,总是收到报错信息 ImportError 确保你创建了 NAME/__init__.py 文件。如果你用的是 Windows,确保你没有不小心把它命名成了 NAME/__init__.py.txt,某些编辑器会有这样的默认设置。

为什么我们需要一个 bin/ 文件夹呢? 这是一个用于存放在命令行运行的脚本的标准地方,它不是一个存放模块的地方。

我的 nosetests 运行结果只显示了一个 test 被运行。这是正确的吗? 是的,我的输出结果也是这样的。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,219评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,363评论 1 293
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,933评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,020评论 0 206
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,400评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,640评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,896评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,597评论 0 199
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,327评论 1 244
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,581评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,072评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,399评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,054评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,083评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,849评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,672评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,585评论 2 270

推荐阅读更多精彩内容