Rendering of reStructured text is not possible, please install Docutils.
:status: 草稿;ZoomQuiet; 90%

.. contents::
  :depth: 3


-4 PyDay 可用的首个脚本
===============================
**寻找吧!不要先想着创造--Python 是自足的**


现在的需求
--------------------
嗯嗯嗯! 小白根据曾经下载过的几个类似商业软件名称, 给自个儿的软件起个名字:  **Python CDCategory** -- Python制作的光盘分类库,简写 ``PyCDC``

再确认当前的需求 ::

  1. 可以将光盘内容索引储存为硬盘上的文本文件
  2. 可以根据储存到硬盘上的光盘信息进行搜索


第一需求是将光盘信息读取为文本文件,因为小白痛恨DB;-)


文件是系统的事儿
----------------------------------------
现在首先的问题是 **如何读取指定目录/分区中的文件列表信息?** 

行者仅仅给了一点批示-- **文件是系统的事儿**


listdir()
``````````````````````````````````````````

系统 -- 操作系统 -- operating system -- `os模块`_

呜乎矣哉! 小白搜索了一大圈才弄明白,什么叫 **系统** , 而且找到了相应的 **模块**

在简明 Python 教程--第14章 Python标准库 -- `os模块`_ 中看到一句话 ::

  os.listdir()返回指定目录下的所有文件和目录名


看起来可以使用,所以,创建我们第一个执行脚本 **PyDay-4-1.py**  ::

  # coding : utf-8
  import os
  print os.listdir("/media/cdrom0")


解释:
  1. ``# coding : utf-8`` 应该作为八股文一样在每个周末头部声明,这是个忠告-- 为了解决中文兼容问题的忠告, 同时你应该选择支持 Unicode 编码的编辑器环境,保证在运行脚本中的每个汉字都是使用 utf-8 编码过的...详细参考...
  2. ``import os`` 就是告诉 Python 环境,我们要使用 `os模块`_ , 以此类推,如何你想使用任何己有的模块包,就使用 **import 模块名** 的形式引用就好
  3. 最后一行才是我们真正想作的事儿:"打印光盘根路径中的所有文件和目录"


脚本:
  - 因为Python程序不用编译,人写的程序文件,可以直接执行,就象话剧脚本一样,所以也称 Python 程序文件为 脚本
  - 在交互式命令行环境中,固然可以立即获得执行结果,但是我们尝试过程中的各种程序代码无法记忆下来,所以,事先写好脚本使用运行命令 ``python 脚本名.py`` 的形式就可以反复执行我们的所有代码行
  - 这是Python 丰富的运行形式之一,也是最常用的一种

运行结果类似:

截屏2-1 |snap_example1|

当然在 `iPython`_  环境下,逐步运行也一样

截屏2-2 |snap_exampleipy1|

以上截屏输出是使用 `Ubuntu`_ 6.06 安装光盘来测试的结果 [#]_ , 当然,小白使用进一步的目录时, ``os.listdir()`` 的确可以报告指定目录的所有信息,但是,问题是如何自动的将整个光盘的所有文件和目录信息都 **一次性扫描** 出来?

当然自个儿写一个也是可以的,不过是根据每级目录的信息,再次不断调用 ``os.listdir()`` 将所有层次的目录信息都逐一汇报出来而已,但是!值得嘛?

小白的热情是非常容易被想起来比较麻烦的现实击碎的...于是热心的无所不能的行者又说了句 **:"使用walk()"**



walk !
``````````````````````````````````````````

又一阵乱搜, 发现居然有个单独的模块 `os.path`_ 就是进行文件路径处理的!

等等! 一通E文后::

  Note: The newer os.walk() generator supplies similar functionality and can be easier to use.

好象在我们的环境中有两个 ``walk()`` -- ``os.path.walk()`` 以及 ``os.walk()`` ,后一个更加新以及好用?

按照 `os-file-dir`_ 的示例改造脚本尝试 **PyDay-4-2.py** ::

  # coding : utf-8
  import os
  for root, dirs, files in os.walk('/media/cdrom0'):
      print root,dirs,files


按照脚本运行方式尝试:``$ python PyDay-4-2.py``... 哇!一下子输出了一大堆的东西! 嗯嗯嗯!看来管用,应该是将整个光盘的文件/目录信息都扫描出来了,
先不管三七二十一,保存为文件先!


输出成文件
``````````````````````````````````````````
根据行者指引,或是搜索,都指向 `file_objects`_ 文件对象操作, 加点儿想象就可以组成以下脚本 **PyDay-4-3.py** ::

  # coding : utf-8
  import os
  for root, dirs, files in os.walk('/media/cdrom0'):
      open('mycd.cdc', 'a').write(root+dirs+files)


执行尝试 ``$python PyDay-4-3.py``

截屏2-3 |snap_4-3|

完了!报错!...嗬嗬嗬,行者说,不用担心,在Python 中的解决bug 是非常轻松的,因为完善的回溯能力,Python 可以非常精确的汇报小白错误的时间,地点,原因,我们只要对应修订就好.

现在的问题是 ``TypeError: cannot concatenate 'str' and 'list' objects`` -- 不能将 **str** 和 **list** 对象进行连接; 嗯嗯嗯,非常直白的数据类型错误,


什么是 **数据类型**? -- 嗯嗯嗯,这问题可以复杂说也可以简单说,复杂的说,并不能帮助小白们理解和记忆,简单的说也不一定可以加深印象,通俗的讲吧,就是计算机内存空间中不同的种族,好比鸡鸭同笼,长的都挻象,但是没有办法买相同的价钱,非常都剁碎了作成春卷 -- 也就是说只要发生类似数据类型不同的时候,转换成相同的类型就得!


这在其它语言可能会很麻烦但是在Python 中是再自然不过的了--因为,``Python 里一切都是对象`` [#]_

讨教行者,给了个样例::

  print "%s %s %s %s" % ("字串",["数","组"],("元","组"),{'字典':123}) 


如果有C编程经验的小白就立即可以联想到这是输出格式化的技巧, 使用``%s`` 的格式化声明,要求后面的对象以 **String** 字串的格式进行转换,所以脚本 **PyDay-4-4.py** 的改造也就顺理成章了 ::

  # coding : utf-8
  import os
  for root, dirs, files in os.walk('/media/cdrom0'):
      open('mycd.cdc', 'a').write("%s %s %s" % (root,dirs,files))


注解:
 1. 声明是 utf-8 编码文本
 2. 引入 os 模块
 3. 使用 os.walk() 扫描光盘,并返回三个对象
 4. 打开'mycd.cdc' 以追加模式,记录以上三个对象

不用怀疑,执行没有报错,而且文件也生成,但是为什么打不开? ... 嗬嗬嗬,那是另一个问题了...


-4 PyDay小结
===============================

通过指点,在文档中狂乱的搜寻,今天小白顺利的将光盘信息全部扫描出来,并存储成了文件!

最后得到的仅仅四行,其实真正运行使用的就两行代码,就可以作到想要的软件功能的50%...嗬嗬嗬,神奇的Python不是?

不过小白接触到了一大批概念:

 1. **模块** -- ``import os``
 2. **内置函式** -- ``open()``
 3. **循环** -- `` for ... in ... ``
 4. **块界定符** 
 5. **注释符** 
 6. **对象**
 7. **文件对象**
 8. **对象转换**
 9. **格式化声明** -- ``%s``
 10. **数据类型**

但是我们的原则是,先用后学,快速获得体验,然后寻求理论支持,所以,先不求甚解,将目的达到,然后就自在了


练习
--------------------

 1.  os 模块中还有哪些功能可以使用? -- 提示使用 ``dir()`` ``help()``
 2. ``open()`` 还有哪些模式可以使用?
 3. 尝试``for .. in ..`` 循环可以对哪些数据类型进行操作?
 4. 格式化声明,还有哪些格式可以进行约定?
 5. 现在的写入文件模式好嘛? 有改进的余地? 

**PyDay-4-5.py** 好在哪里? ::

  # coding : utf-8
  import os
  export = ""
  for root, dirs, files in os.walk('/media/cdrom0'):
      export+="\n %s;%s;%s" % (root,dirs,files)
  open('mycd2.cdc', 'w').write(export)



.. os模块:http://www.woodpecker.org.cn:9081/doc/abyteofpython_cn/chinese/ch14s03.html
.. iPython:http://ipython.scipy.org/moin/
.. Ubuntu:http://www.ubuntu.org.cn/
.. os.path:http://aspn.activestate.com/ASPN/docs/ActivePython/2.4/python/lib/module-os.path.html
.. os-file-dir:http://aspn.activestate.com/ASPN/docs/ActivePython/2.4/python/lib/os-file-dir.html
.. file_objects:http://www.woodpecker.org.cn/diveintopython/file_handling/file_objects.html#id2641998

.. |snap_example1| image:: snap_example1.png
.. |snap_exampleipy1| image:: snap_exampleipy1.png
.. |snap_4-3| image:: snap_4-3.png

.. [#] 笔者使用 Ubuntu 系统, 是种GNU/Linux 系统,对于文件系统的使用和广大小白们使用 Windows 系统稍有不同,
  没有分区的概念,光盘一般会自动统一的挂接到 ``/media/cdrom0`` 目录,
  小白们,当然可以自由的使用 "G:\" 等等类似的盘符进行替换,放心 Python 足够聪明,她是跨平台的
.. [#] 这是理解,应用Python 的关键句之一,详细的参考...




.. macro:: [[PageComment2(nosmiley=1, notify=1)]]


.. macro:: -- ZoomQuiet [[[DateTime(2007-02-20T07:11:54Z)]]]

ObpLovelyPython/PyDay-4 (last edited 2009-12-25 07:14:48 by localhost)